// 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
	}
	if !header.IsSupportedVersion() {
		return ErrUnknownMagic
	}
	// 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,
	}
	if newCtx().EncodeUnionsAsXUnionBytes {
		header.SetUnionFromXunionBytes()
	}
	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)

	// close channel on error
	hasFailed := true
	defer func() {
		if hasFailed {
			p.Channel.Close()
		}
	}()

	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
	}

	err := unmarshalForOrdinal(ordinal, respb[:nb], resph[:nh], resp, gen_ordinal...)
	if err != nil {
		return err
	}

	hasFailed = false
	return nil
}

// 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)

	// close channel on error
	hasFailed := true
	defer func() {
		if hasFailed {
			p.Channel.Close()
		}
	}()

	// Marshal the message into the buffer
	header := MessageHeader{
		Ordinal: ordinal,
		Magic:   FidlWireFormatMagicNumberInitial,
	}
	if newCtx().EncodeUnionsAsXUnionBytes {
		header.SetUnionFromXunionBytes()
	}
	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
	}

	err = unmarshalForOrdinal(ordinal, respb[:cnb], resph[:cnh], resp, gen_ordinal...)
	if err != nil {
		return err
	}

	hasFailed = false
	return nil
}
