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

// Directory is a wrapper around a DirectoryAdminInterface which implements FDIO.
type Directory struct {
	Node
}

func (d *Directory) getToken() (zx.Handle, error) {
	status, token, err := d.DirectoryInterface().GetToken()
	if err != nil {
		return zx.HandleInvalid, err
	} else if status != zx.ErrOk {
		return zx.HandleInvalid, zx.Error{Status: status, Text: "io.directory"}
	}
	return token, nil
}

// DirectoryInterface returns the underlying Directory FIDL interface.
// It lies a little, in the sense that it always returns a "DirectoryAdminInterface"
// for convenience.
func (d *Directory) DirectoryInterface() *io.DirectoryAdminInterface {
	return (*io.DirectoryAdminInterface)(d.Node.NodeInterface)
}

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

// Open opens an FDIO at path with the given flags and mode relative to this
// Directory.
func (d *Directory) Open(pathname string, flags uint32, mode uint32) (FDIO, error) {
	req, obj, err := io.NewNodeInterfaceRequest()
	if err != nil {
		return nil, err
	}
	err = d.DirectoryInterface().Open(flags|io.OpenFlagDescribe, mode, pathname, req)
	if err != nil {
		((*fidl.Proxy)(obj)).Close()
		return nil, err
	}
	status, info, err := obj.ExpectOnOpen()
	if err != nil {
		((*fidl.Proxy)(obj)).Close()
		return nil, err
	} else if status != zx.ErrOk {
		((*fidl.Proxy)(obj)).Close()
		return nil, zx.Error{Status: status, Text: "io.directory"}
	}
	return nodeFromInfo(info, obj)
}

func (d *Directory) openParent(pathname string) (FDIO, string, error) {
	dirpath, name := pathSplit(pathname)
	parent, err := d.Open(pathDir(dirpath), io.OpenRightReadable, io.OpenFlagDirectory)
	if err != nil {
		return nil, "", err
	}
	return parent, name, err
}

// Link creates a link between two paths under this Directory.
func (d *Directory) Link(oldpath, newpath string) error {
	oldparent, oldname, err := d.openParent(oldpath)
	if err != nil {
		return err
	}
	defer oldparent.Close()
	newparent, newname, err := d.openParent(newpath)
	if err != nil {
		return err
	}
	defer newparent.Close()
	olddir, ok := oldparent.(*Directory)
	if !ok {
		return zx.Error{Status: zx.ErrNotSupported, Text: "io.directory"}
	}
	newdir, ok := newparent.(*Directory)
	if !ok {
		return zx.Error{Status: zx.ErrNotSupported, Text: "io.directory"}
	}
	token, err := newdir.getToken()
	if err != nil {
		return err
	}
	status, err := olddir.DirectoryInterface().Link(oldname, token, newname)
	if err != nil {
		return err
	} else if status != zx.ErrOk {
		return zx.Error{Status: status, Text: "io.directory"}
	}
	return nil
}

// Rename renames an object at one path to another under this Directory.
func (d *Directory) Rename(oldpath, newpath string) error {
	oldf, oldname, err := d.openParent(oldpath)
	if err != nil {
		return err
	}
	defer oldf.Close()
	newf, newname, err := d.openParent(newpath)
	if err != nil {
		return err
	}
	defer newf.Close()
	olddir, ok := oldf.(*Directory)
	if !ok {
		return zx.Error{Status: zx.ErrNotSupported, Text: "io.directory"}
	}
	newdir, ok := newf.(*Directory)
	if !ok {
		return zx.Error{Status: zx.ErrNotSupported, Text: "io.directory"}
	}
	token, err := newdir.getToken()
	if err != nil {
		return err
	}
	status, err := olddir.DirectoryInterface().Rename(oldname, token, newname)
	if err != nil {
		return err
	} else if status != zx.ErrOk {
		return zx.Error{Status: status, Text: "io.directory"}
	}
	return nil
}

// Unlink unlinks an object at a pauth under this Directory.
func (d *Directory) Unlink(pathname string) error {
	parent, name, err := d.openParent(pathname)
	if err != nil {
		return err
	}
	defer parent.Close()
	parentdir, ok := parent.(*Directory)
	if !ok {
		return zx.Error{Status: zx.ErrNotSupported, Text: "io.directory"}
	}
	if status, err := parentdir.DirectoryInterface().Unlink(name); err != nil {
		return err
	} else if status != zx.ErrOk {
		return zx.Error{Status: status, Text: "io.directory"}
	}
	return nil
}

// ReadDirents returns up to max-worth bytes of byte-encoded dirents which represent
// objects under this Directory. Repeated calls to ReadDirents continues giving back
// objects.
func (d *Directory) ReadDirents(max uint64) ([]byte, error) {
	status, dirents, err := d.DirectoryInterface().ReadDirents(max)
	if err != nil {
		return nil, err
	} else if status != zx.ErrOk {
		return nil, zx.Error{Status: status, Text: "io.file"}
	}
	return dirents, nil
}

// Rewind resets the ReadDirents' counter.
func (d *Directory) Rewind() error {
	if status, err := d.DirectoryInterface().Rewind(); err != nil {
		return err
	} else if status != zx.ErrOk {
		return zx.Error{Status: status, Text: "io.directory"}
	}
	return nil
}
