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

import (
	"syscall/zx"
	"syscall/zx/fidl"
	"syscall/zx/io"
)

func nodeFromInfo(info *io.NodeInfo, node *io.NodeInterface) (result FDIO, err error) {
	if info == nil {
		if err = ((*fidl.Proxy)(node)).Channel.Close(); err != nil {
			return nil, err
		}
		return nil, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
	}
	switch info.NodeInfoTag {
	case io.NodeInfoService:
		// TODO(mknyszek): Figure out the correct type to return here.
		result = &Node{NodeInterface: node}
	case io.NodeInfoFile:
		result = &File{
			Node:  Node{NodeInterface: node},
			Event: info.File.Event,
		}
	case io.NodeInfoDevice:
		result = &File{
			Node:  Node{NodeInterface: node},
			Event: info.Device.Event,
		}
	case io.NodeInfoDirectory:
		result = &Directory{Node: Node{NodeInterface: node}}
	case io.NodeInfoPipe:
		if err = ((*fidl.Proxy)(node)).Channel.Close(); err != nil {
			return nil, err
		}
		result = NewPipe(info.Pipe.Socket)
	case io.NodeInfoVmofile:
		if err = ((*fidl.Proxy)(node)).Channel.Close(); err != nil {
			return nil, err
		}
		result, err = NewVMOFile(info.Vmofile.Vmo, info.Vmofile.Offset, info.Vmofile.Length)
		if err != nil {
			return nil, err
		}
	default:
		if err = ((*fidl.Proxy)(node)).Channel.Close(); err != nil {
			return nil, err
		}
		return nil, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
	}
	return result, nil
}

// Node is a wrapper around an NodeInterface which implements FDIO.
type Node struct {
	*io.NodeInterface
}

// IsValid returns true if the Node is valid.
func (n *Node) IsValid() bool {
	if n.NodeInterface == nil {
		return false
	}
	return ((*fidl.Proxy)(n.NodeInterface)).IsValid()
}

// Handles returns a slice of untyped zx handles containing the underlying
// channel of the Node.
func (n *Node) Handles() []zx.Handle {
	return []zx.Handle{
		zx.Handle(((*fidl.Proxy)(n.NodeInterface)).Channel),
	}
}

// Clone makes a clone of the node.
func (n *Node) Clone() (FDIO, error) {
	req, newNode, err := io.NewNodeInterfaceRequest()
	if err != nil {
		return nil, err
	}
	if err := n.NodeInterface.Clone(io.OpenFlagDescribe, req); err != nil {
		((*fidl.Proxy)(newNode)).Close()
		return nil, err
	}
	status, info, err := newNode.ExpectOnOpen()
	if err != nil {
		((*fidl.Proxy)(newNode)).Close()
		return nil, err
	} else if status != zx.ErrOk {
		((*fidl.Proxy)(newNode)).Close()
		return nil, zx.Error{Status: status, Text: "io.node"}
	}
	return nodeFromInfo(info, newNode)
}

// Close closes the node.
func (n *Node) Close() error {
	defer ((*fidl.Proxy)(n.NodeInterface)).Close()
	if status, err := n.NodeInterface.Close(); err != nil {
		return err
	} else if status != zx.ErrOk {
		return zx.Error{Status: status, Text: "io.node"}
	}
	return nil
}

// Sync performs a sync operation on a Node.
func (n *Node) Sync() error {
	if status, err := n.NodeInterface.Sync(); err != nil {
		return err
	} else if status != zx.ErrOk {
		return zx.Error{Status: status, Text: "io.node"}
	}
	return nil
}

// GetAttr returns the attributes for the Node.
func (n *Node) GetAttr() (io.NodeAttributes, error) {
	status, attrs, err := n.NodeInterface.GetAttr()
	if err != nil {
		return io.NodeAttributes{}, err
	} else if status != zx.ErrOk {
		return io.NodeAttributes{}, zx.Error{Status: status, Text: "io.node"}
	}
	return attrs, nil
}

// SetAttr sets the attributes for Node as defined by flags.
func (n *Node) SetAttr(flags uint32, attr io.NodeAttributes) error {
	if status, err := n.NodeInterface.SetAttr(flags, attr); err != nil {
		return err
	} else if status != zx.ErrOk {
		return zx.Error{Status: status, Text: "io.node"}
	}
	return nil
}

// Ioctl calls an ioctl on Node.
func (n *Node) Ioctl(op uint32, max uint64, in []byte, handles []zx.Handle) ([]byte, []zx.Handle, error) {
	status, h, b, err := n.NodeInterface.Ioctl(op, max, handles, in)
	if err != nil {
		return nil, nil, err
	} else if status != zx.ErrOk {
		return nil, nil, zx.Error{Status: status, Text: "io.node"}
	}
	return b, h, nil
}

// Read implements FDIO for Node.
func (n *Node) Read(data []byte) (int, error) {
	return 0, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}

// ReadAt implements FDIO for Node.
func (n *Node) ReadAt(data []byte, off int64) (int, error) {
	return 0, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}

// Write implements FDIO for Node.
func (n *Node) Write(data []byte) (int, error) {
	return 0, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}

// WriteAt implements FDIO for Node.
func (n *Node) WriteAt(data []byte, off int64) (int, error) {
	return 0, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}

// Seek implements FDIO for Node.
func (n *Node) Seek(offset int64, whence int) (int64, error) {
	return 0, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}

// Truncate implements FDIO for Node.
func (n *Node) Truncate(length uint64) error {
	return zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}

// Open implements FDIO for Node.
func (n *Node) Open(path string, flags uint32, mode uint32) (FDIO, error) {
	return nil, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}

// Link implements FDIO for Node.
func (n *Node) Link(oldpath, newpath string) error {
	return zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}

// Rename implements FDIO for Node.
func (n *Node) Rename(oldpath, newpath string) error {
	return zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}

// Unlink implements FDIO for Node.
func (n *Node) Unlink(path string) error {
	return zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}

// ReadDirents implements FDIO for Node.
func (n *Node) ReadDirents(max uint64) ([]byte, error) {
	return nil, zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}

// Rewind implements FDIO for Node.
func (n *Node) Rewind() error {
	return zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
}
