// Copyright 2016 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 net

import (
	"context"
	"fmt"
	"sync"
	"syscall"
	"syscall/zx"
	"syscall/zx/fdio"
	"syscall/zx/net"
	"syscall/zx/posix/socket"
	"syscall/zx/zxsocket"
)

func (p *ipStackCapabilities) probe() {
	p.ipv4Enabled = true
	p.ipv6Enabled = true
	p.ipv4MappedIPv6Enabled = true
}

// A sockaddr represents a TCP, UDP, IP or Unix network endpoint
// address that can be converted into an fdio sockaddr message.
type sockaddr interface {
	Addr

	family() int
	domain() socket.Domain
	isWildcard() bool
	sockaddr(domain socket.Domain) (addr net.SocketAddress, err error)
}

func favoriteAddrDomain(net string, laddr, raddr sockaddr, mode string) socket.Domain {
	switch net[len(net)-1] {
	case '4':
		return socket.DomainIpv4
	case '6':
		return socket.DomainIpv6
	}

	if mode == "listen" && (laddr == nil || laddr.isWildcard()) {
		if supportsIPv4map() || !supportsIPv4() {
			return socket.DomainIpv6
		}
		if laddr == nil {
			return socket.DomainIpv4
		}
		return laddr.domain()
	}

	if (laddr == nil || laddr.domain() == socket.DomainIpv4) &&
		(raddr == nil || raddr.domain() == socket.DomainIpv4) {
		return socket.DomainIpv4
	}
	return socket.DomainIpv6
}

var socketProvider struct {
	once     sync.Once
	provider socket.ProviderWithCtxInterface
	err      error
}

func getProvider() (*socket.ProviderWithCtxInterface, error) {
	socketProvider.once.Do(func() {
		socketProvider.err = func() error {
			c0, c1, err := zx.NewChannel(0)
			if err != nil {
				return err
			}
			if err := fdio.ServiceConnect("/svc/"+socket.ProviderName, zx.Handle(c0)); err != nil {
				_ = c1.Close()
				return err
			}
			socketProvider.provider.Channel = c1
			return nil
		}()
	})
	return &socketProvider.provider, socketProvider.err
}

func dialFuchsia(_ context.Context, netName string, laddr, raddr sockaddr) (*netFD, error) {
	domain := favoriteAddrDomain(netName, laddr, raddr, "dial")

	provider, err := getProvider()
	if err != nil {
		return nil, err
	}

	var base *socket.BaseSocketWithCtxInterface
	if stringsHasPrefix(netName, "udp") {
		result, err := provider.DatagramSocket(context.Background(), domain, socket.DatagramSocketProtocolUdp)
		if err != nil {
			return nil, err
		}
		switch result.Which() {
		case socket.ProviderDatagramSocketResultErr:
			return nil, syscall.Errno(result.Err)
		case socket.ProviderDatagramSocketResultResponse:
			base = &socket.BaseSocketWithCtxInterface{Channel: result.Response.S.Channel}
		default:
			panic(fmt.Sprintf("unrecognized fuchsia.posix.socket/Provider.DatagramSocket result %d", result.Which()))
		}
	} else {
		result, err := provider.StreamSocket(context.Background(), domain, socket.StreamSocketProtocolTcp)
		if err != nil {
			return nil, err
		}
		switch result.Which() {
		case socket.ProviderStreamSocketResultErr:
			return nil, syscall.Errno(result.Err)
		case socket.ProviderStreamSocketResultResponse:
			base = &socket.BaseSocketWithCtxInterface{Channel: result.Response.S.Channel}
		default:
			panic(fmt.Sprintf("unrecognized fuchsia.posix.socket/Provider.StreamSocket result %d", result.Which()))
		}
	}

	sock, err := zxsocket.NewSocket(base)
	if err != nil {
		return nil, err
	}
	fd := newFD(sock, domain, netName)
	if laddr != nil {
		addr, err := laddr.sockaddr(domain)
		if err != nil {
			return nil, err
		}
		var port uint16
		isSet := false
		switch addr.Which() {
		case net.SocketAddressIpv4:
			port = addr.Ipv4.Port
			isSet = true
		case net.SocketAddressIpv6:
			port = addr.Ipv6.Port
			isSet = true
		}
		if isSet || port != 0 {
			if err := fd.sock.Bind(addr); err != nil {
				return nil, err
			}
		}
		if raddr == nil {
			switch s := fd.sock.(type) {
			case *zxsocket.DatagramSocket:
			case *zxsocket.StreamSocket:
				if err := s.Listen(int16(listenerBacklog())); err != nil {
					return nil, err
				}
			default:
				panic(fmt.Sprintf("unrecognized socket type %T", fd.sock))
			}
		}
	}
	if raddr != nil {
		addr, err := raddr.sockaddr(domain)
		if err != nil {
			return nil, err
		}
		for i := 0; i < 2; i++ {
			err = fd.sock.Connect(addr)
			if sock, ok := fd.sock.(*zxsocket.StreamSocket); ok && err == syscall.EINPROGRESS {
				obs, err := sock.Wait(zxsocket.SignalOutgoing|zx.SignalSocketPeerClosed, zx.TimensecInfinite)
				if err != nil {
					return nil, err
				}
				switch {
				case obs&zx.SignalSocketPeerClosed != 0:
					return nil, &zx.Error{Status: zx.ErrPeerClosed, Text: "zxsocket"}
				case obs&zxsocket.SignalOutgoing != 0:
					// Call connect again to learn the result.
					continue
				default:
					panic(fmt.Sprintf("unexpected observed signals %08X", obs))
				}
			}
			break
		}
		if err != nil {
			return nil, err
		}
		fd.isConnected = true
	}
	fd.setAddr()

	return fd, nil
}

func ipToSockaddr(domain socket.Domain, ip IP, port int, zone_str string) (address net.SocketAddress, err error) {
	switch domain {
	case socket.DomainIpv4:
		if len(ip) == 0 {
			ip = IPv4zero
		}
		ip4 := ip.To4()
		if ip4 == nil {
			return net.SocketAddress{}, &AddrError{Err: "non-IPv4 address", Addr: ip.String()}
		}
		addr := net.SocketAddressWithIpv4(net.Ipv4SocketAddress{
			Port: uint16(port),
		})
		copy(addr.Ipv4.Address.Addr[:], ip4)
		return addr, nil
	case socket.DomainIpv6:
		if len(ip) == 0 || ip.Equal(IPv4zero) {
			ip = IPv6zero
		}
		ip6 := ip.To16()
		if ip6 == nil {
			return net.SocketAddress{}, &AddrError{Err: "non-IPv6 address", Addr: ip.String()}
		}
		addr := net.SocketAddressWithIpv6(net.Ipv6SocketAddress{
			Port:      uint16(port),
			ZoneIndex: uint64(zoneCache.index(zone_str)),
		})
		copy(addr.Ipv6.Address.Addr[:], ip6)
		return addr, nil
	}
	return net.SocketAddress{}, &AddrError{Err: "invalid address family", Addr: ip.String()}
}
