// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build fuchsia

package fidl

import (
	"strconv"
	"syscall/zx"
	"syscall/zx/zxwait"
)

// ServiceRequest is an abstraction over a FIDL interface request which is
// intended to be used as part of service discovery.
type ServiceRequest interface {
	// Name returns the name of the service being requested.
	Name() string

	// ToChannel returns the underlying channel of the ServiceRequest.
	ToChannel() zx.Channel
}

// InterfaceRequest is a wrapper type around a channel and represents the server side
// of a FIDL interface, to be sent to a server as a request.
type InterfaceRequest struct {
	zx.Channel
}

// NewInterfaceRequest generates two sides of a channel with one layer of
// type casts out of the way to minimize the amount of generated code. Semantically,
// the two sides of the channel represent the interface request and the client
// side of the interface (the proxy). It returns an error on failure.
func NewInterfaceRequest() (InterfaceRequest, *ChannelProxy, error) {
	h0, h1, err := zx.NewChannel(0)
	if err != nil {
		return InterfaceRequest{}, nil, err
	}
	return InterfaceRequest{Channel: h0}, &ChannelProxy{Channel: h1}, nil
}

// Proxy represents the client side of a FIDL interface.
type Proxy interface {
	IsValid() bool
	Send(ordinal uint64, req Message) error
	// TODO(FIDL-524): Remove `gen_ordinal` post-ordinal migration.
	Recv(ordinal uint64, resp Message, gen_ordinal ...uint64) error
	Call(ordinal uint64, req Message, resp Message, gen_ordinal ...uint64) error
}

// Stub represents a generated type which wraps the server-side implementation of a
// FIDL interface.
//
// It contains logic which is able to dispatch into the correct implementation given
// the incoming message ordinal and its data.
type Stub interface {
	// DispatchImpl dispatches into the appropriate method implementation for a FIDL
	// interface by using the ordinal.
	//
	// It also takes the data as bytes and transforms it into arguments usable by
	// the method implementation. It then optionally returns a response if the
	// method has a response, in which case, the boolean return value is true.
	DispatchImpl(ordinal uint64, bytes []byte, handles []zx.Handle) (Message, bool, error)
}

// ChannelProxy a Proxy that is backed by a channel.
type ChannelProxy struct {
	// Channel is the underlying channel endpoint for this interface.
	zx.Channel
}

// Assert that ChannelProxy implements the Proxy interface.
var _ Proxy = &ChannelProxy{}

// IsValid returns true if the underlying channel is a valid handle.
func (p *ChannelProxy) IsValid() bool {
	return p.Channel.Handle().IsValid()
}

func withRetry(fn func() error, handle zx.Handle, ready, closed zx.Signals) error {
	signals := ready | closed
	for {
		err := fn()
		if err, ok := err.(*zx.Error); ok && err.Status == zx.ErrShouldWait {
			obs, err := zxwait.Wait(
				handle,
				signals,
				zx.TimensecInfinite,
			)
			if err != nil {
				return err
			}
			if obs&ready != 0 {
				continue
			}
			if obs&closed != 0 {
				return &zx.Error{Status: zx.ErrPeerClosed}
			}
			panic("unexpected signal mask " + strconv.FormatUint(uint64(obs), 2) + " (expected " + strconv.FormatUint(uint64(signals), 2) + ")")
		}
		return err
	}
}

func unmarshalForOrdinal(ordinal uint64, respb []byte, resph []zx.Handle, resp Message, gen_ordinal ...uint64) error {
	var header MessageHeader
	if err := UnmarshalHeaderThenMessage(respb, resph, &header, resp); err != nil {
		return err
	}
	// TODO(FIDL-524): Remove temporary handling of two ordinals.
	expectedOrdinal := header.Ordinal == ordinal
	expectedOrdinals := []uint64{ordinal}
	for _, ordinal := range gen_ordinal {
		expectedOrdinal = expectedOrdinal || header.Ordinal == ordinal
		expectedOrdinals = append(expectedOrdinals, ordinal)
	}
	if !expectedOrdinal {
		return newExpectError(ErrUnexpectedOrdinal, expectedOrdinals, header.Ordinal)
	}
	return nil
}

// Send sends the request over the channel with the specified ordinal
// without a response.
func (p *ChannelProxy) Send(ordinal uint64, req Message) error {
	respb := messageBytesPool.Get().([]byte)
	resph := messageHandlesPool.Get().([]zx.Handle)

	defer messageBytesPool.Put(respb)
	defer messageHandlesPool.Put(resph)

	// Marshal the message into the buffer.
	header := MessageHeader{
		Txid:    0, // Txid == 0 for messages without a response.
		Ordinal: ordinal,
		Magic:   FidlWireFormatMagicNumberInitial,
	}
	nb, nh, err := MarshalHeaderThenMessage(&header, req, respb[:], resph[:])
	if err != nil {
		return err
	}

	// Write the encoded bytes to the channel.
	return withRetry(func() error {
		return p.Channel.Write(respb[:nb], resph[:nh], 0)
	}, *p.Channel.Handle(), zx.SignalChannelWritable, zx.SignalChannelPeerClosed)
}

// Recv waits for an event and writes the response into the response.
func (p *ChannelProxy) Recv(ordinal uint64, resp Message, gen_ordinal ...uint64) error {
	respb := messageBytesPool.Get().([]byte)
	resph := messageHandlesPool.Get().([]zx.Handle)

	defer messageBytesPool.Put(respb)
	defer messageHandlesPool.Put(resph)

	var nb, nh uint32
	if err := withRetry(func() error {
		var err error
		nb, nh, err = p.Channel.Read(respb[:], resph[:], 0)
		return err
	}, *p.Channel.Handle(), zx.SignalChannelReadable, zx.SignalChannelPeerClosed); err != nil {
		return err
	}

	return unmarshalForOrdinal(ordinal, respb[:nb], resph[:nh], resp, gen_ordinal...)
}

// Call sends the request over the channel with the specified ordinal
// and synchronously waits for a response. It then writes the response into the
// response.
func (p *ChannelProxy) Call(ordinal uint64, req Message, resp Message, gen_ordinal ...uint64) error {
	respb := messageBytesPool.Get().([]byte)
	resph := messageHandlesPool.Get().([]zx.Handle)

	defer messageBytesPool.Put(respb)
	defer messageHandlesPool.Put(resph)

	// Marshal the message into the buffer
	header := MessageHeader{
		Ordinal: ordinal,
		Magic:   FidlWireFormatMagicNumberInitial,
	}
	nb, nh, err := MarshalHeaderThenMessage(&header, req, respb[:], resph[:])
	if err != nil {
		return err
	}

	// Make the IPC call.
	cnb, cnh, err := p.Channel.Call(0, zx.TimensecInfinite, respb[:nb], resph[:nh], respb[:], resph[:])
	if err != nil {
		return err
	}

	return unmarshalForOrdinal(ordinal, respb[:cnb], resph[:cnh], resp, gen_ordinal...)
}
