// 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 {
	// DispatchImplWithCtx 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.
	DispatchImplWithCtx(ordinal uint64, ctx MarshalerContext, 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.
	reqHeader := newCtx().NewHeader()
	reqHeader.Txid = 0
	reqHeader.Ordinal = ordinal
	nb, nh, err := MarshalHeaderThenMessage(&reqHeader, 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()
		}
	}()

	reqHeader := newCtx().NewHeader()
	reqHeader.Txid = 0
	reqHeader.Ordinal = ordinal
	nb, nh, err := MarshalHeaderThenMessage(&reqHeader, 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
}
