// 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 {
			if err = ((*fidl.Proxy)(node)).Channel.Close(); err != nil {
				return nil, err
			}
			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"}
}
