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

// TODO: move to using fd_unix for fuchsia?

package net

import (
	"errors"
	"fmt"
	"internal/poll"
	"os"
	"runtime"
	"syscall"
	"syscall/zx/net"
	"syscall/zx/posix/socket"
	"syscall/zx/zxsocket"
	"time"
)

// Network file descriptor.
type netFD struct {
	pfd poll.FD

	// immutable until Close
	sock        zxsocket.Socket
	net         string
	family      int
	isConnected bool
	laddr       Addr
	raddr       Addr
}

func domainToFamily(domain socket.Domain) int {
	switch domain {
	case socket.DomainIpv4:
		return syscall.AF_INET
	case socket.DomainIpv6:
		return syscall.AF_INET6
	default:
		panic(fmt.Sprintf("unrecognized socket domain %s(%d)", domain, domain))
	}
}

func familyToDomain(family int) socket.Domain {
	switch family {
	case syscall.AF_INET:
		return socket.DomainIpv4
	case syscall.AF_INET6:
		return socket.DomainIpv6
	default:
		panic(fmt.Sprintf("unrecognized socket family %d", family))
	}
}

func newFD(sock zxsocket.Socket, domain socket.Domain, net string) *netFD {
	return &netFD{
		pfd: poll.FD{
			Sysfd: syscall.OpenFDIO(sock),
		},
		sock:   sock,
		family: domainToFamily(domain),
		net:    net,
	}
}

func (fd *netFD) init() error {
	// TODO: flip to true after implementing netpoller for real
	return fd.pfd.Init(fd.net, false)
}

func (fd *netFD) isTCP() bool {
	return len(fd.net) >= 3 && fd.net[:3] == "tcp"
}

func (fd *netFD) Read(b []byte) (n int, err error) {
	n, err = fd.pfd.Read(b)
	runtime.KeepAlive(fd)
	return n, err
}

func (fd *netFD) Write(b []byte) (n int, err error) {
	n, err = fd.pfd.Write(b)
	runtime.KeepAlive(fd)
	return n, err
}

func (fd *netFD) readMsg(b []byte) (n, flags int, addr net.SocketAddress, err error) {
	// TODO: move call to pfd
	data, addr, err := fd.sock.(*zxsocket.DatagramSocket).RecvMsg(len(b))
	runtime.KeepAlive(fd)
	n = copy(b, data)
	return n, 0, addr, err
}

func (fd *netFD) sendMsg(b []byte, addr net.SocketAddress) (n int, err error) {
	// TODO: move call to pfd
	n, err = fd.sock.(*zxsocket.DatagramSocket).SendMsg(b, addr)
	runtime.KeepAlive(fd)
	return n, err
}

func (fd *netFD) closeRead() error {
	return errors.New("net: closeRead not implemented on fuchsia")
}

func (fd *netFD) closeWrite() error {
	return errors.New("net: closeWrite not implemented on fuchsia")
}

func (fd *netFD) Close() error {
	return fd.pfd.Close()
}

func (fd *netFD) dup() (*os.File, error) {
	fdio, err := fd.sock.Clone()
	if err != nil {
		return nil, err
	}
	return os.NewFile(uintptr(syscall.OpenFDIO(fdio)), fd.name()), nil
}

func (fd *netFD) accept() (*netFD, error) {
	newm, err := fd.pfd.Accept()
	if err != nil {
		return nil, err
	}
	netfd := newFD(newm, familyToDomain(fd.family), fd.net)
	if err := netfd.init(); err != nil {
		fd.Close()
		return nil, err
	}
	netfd.setAddr()
	return netfd, nil
}

func socketAddrToIpPort(addr net.SocketAddress) (IP, int) {
	switch addr.Which() {
	case net.SocketAddressIpv4:
		return addr.Ipv4.Address.Addr[:], int(addr.Ipv4.Port)
	case net.SocketAddressIpv6:
		return addr.Ipv6.Address.Addr[:], int(addr.Ipv6.Port)
	default:
		panic(fmt.Sprintf("unrecognized SocketAddress variant %d", addr.Which()))
	}
}

func (fd *netFD) asAddr(addr net.SocketAddress, err error) sockaddr {
	if err != nil {
		return nil
	}

	ip, port := socketAddrToIpPort(addr)
	if isZeros(ip) && port == 0 {
		return nil
	}

	switch fd.sock.(type) {
	case *zxsocket.DatagramSocket:
		return &UDPAddr{IP: ip, Port: port}
	case *zxsocket.StreamSocket:
		return &TCPAddr{IP: ip, Port: port}
	default:
		panic(fmt.Sprintf("unrecognized socket type %T", fd.sock))
	}
}

func (fd *netFD) setAddr() {
	fd.laddr = fd.asAddr(fd.sock.GetSockName())
	fd.raddr = fd.asAddr(fd.sock.GetPeerName())
	runtime.SetFinalizer(fd, (*netFD).Close)
}

func (fd *netFD) name() string {
	var ls, rs string
	if fd.laddr != nil {
		ls = fd.laddr.String()
	}
	if fd.raddr != nil {
		rs = fd.raddr.String()
	}
	return fd.net + ":" + ls + "->" + rs
}

func (fd *netFD) SetDeadline(t time.Time) error {
	return fd.pfd.SetDeadline(t)
}

func (fd *netFD) SetReadDeadline(t time.Time) error {
	return fd.pfd.SetReadDeadline(t)
}

func (fd *netFD) SetWriteDeadline(t time.Time) error {
	return fd.pfd.SetWriteDeadline(t)
}
