// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package msdosfs

import (
	"sync"
	"time"

	"go.fuchsia.dev/fuchsia/src/lib/thinfs/fs"
	"go.fuchsia.dev/fuchsia/src/lib/thinfs/fs/msdosfs/node"
)

type directory struct {
	fs    *fsFAT
	node  node.DirectoryNode
	flags fs.OpenFlags // Original flags which opened this directory

	sync.RWMutex
	closed bool
}

// Ensure the directory implements the fs.Directory interface
var _ fs.Directory = (*directory)(nil)

func (d *directory) Close() error {
	d.fs.RLock()
	defer d.fs.RUnlock()
	if d.fs.unmounted {
		return fs.ErrUnmounted
	}
	d.Lock()
	defer d.Unlock()
	if d.closed {
		return fs.ErrNotOpen
	}
	d.closed = true

	return closeDirectory(d.node, false)
}

func (d *directory) Stat() (int64, time.Time, time.Time, error) {
	d.fs.RLock()
	defer d.fs.RUnlock()
	if d.fs.unmounted {
		return 0, time.Time{}, time.Time{}, fs.ErrUnmounted
	}
	d.RLock()
	defer d.RUnlock()
	if d.closed {
		return 0, time.Time{}, time.Time{}, fs.ErrNotOpen
	}

	return stat(d.node)
}

func (d *directory) Touch(lastAccess, lastModified time.Time) error {
	d.fs.RLock()
	defer d.fs.RUnlock()
	if d.fs.unmounted {
		return fs.ErrUnmounted
	}
	d.RLock()
	defer d.RUnlock()
	if d.closed {
		return fs.ErrNotOpen
	}

	touch(d.node, lastAccess, lastModified)
	return nil
}

func (d *directory) Dup() (fs.Directory, error) {
	d.fs.RLock()
	defer d.fs.RUnlock()
	if d.fs.unmounted {
		return nil, fs.ErrUnmounted
	}
	d.RLock()
	defer d.RUnlock()
	if d.closed {
		return nil, fs.ErrNotOpen
	}

	dup(d.node)

	return &directory{
		fs:    d.fs,
		node:  d.node,
		flags: d.flags,
	}, nil
}

func (d *directory) Reopen(flags fs.OpenFlags) (fs.Directory, error) {
	d.fs.RLock()
	defer d.fs.RUnlock()
	if d.fs.unmounted {
		return nil, fs.ErrUnmounted
	}
	d.RLock()
	defer d.RUnlock()
	if d.closed {
		return nil, fs.ErrNotOpen
	}

	if (flags.Read() && !d.flags.Read()) || (flags.Write() && !d.flags.Write()) {
		return nil, fs.ErrPermission
	} else if flags.File() {
		return nil, fs.ErrNotAFile
	}

	dup(d.node)
	return &directory{
		fs:    d.fs,
		node:  d.node,
		flags: d.flags,
	}, nil
}

func (d *directory) Read() ([]fs.Dirent, error) {
	d.fs.RLock()
	defer d.fs.RUnlock()
	if d.fs.unmounted {
		return nil, fs.ErrUnmounted
	}
	d.RLock()
	defer d.RUnlock()
	if d.closed {
		return nil, fs.ErrNotOpen
	}
	if d.flags.Path() {
		return nil, fs.ErrPermission
	}

	return readDir(d.node)
}

func (d *directory) Open(name string, flags fs.OpenFlags) (fs.File, fs.Directory, *fs.Remote, error) {
	d.fs.RLock()
	defer d.fs.RUnlock()
	if d.fs.unmounted {
		return nil, nil, nil, fs.ErrUnmounted
	}
	d.RLock()
	defer d.RUnlock()
	if d.closed {
		return nil, nil, nil, fs.ErrNotOpen
	}

	if (flags.Write() || flags.Create()) && d.fs.info.Readonly {
		return nil, nil, nil, fs.ErrPermission
	} else if flags.Create() && !d.flags.Write() {
		return nil, nil, nil, fs.ErrPermission // Creation requires the parent directory to be writable
	} else if !flags.Read() && !flags.Write() && !flags.Path() {
		return nil, nil, nil, fs.ErrPermission // Cannot open a file with no permissions
	}

	n, err := open(d.node, name, flags)
	if err != nil {
		return nil, nil, nil, err
	}

	if n.IsDirectory() {
		return nil, &directory{
			fs:    d.fs,
			node:  n.(node.DirectoryNode),
			flags: flags | fs.OpenFlagWrite | fs.OpenFlagRead,
		}, nil, nil
	}
	return &file{
		fs:       d.fs,
		node:     n.(node.FileNode),
		flags:    flags,
		position: &filePosition{},
	}, nil, nil, nil
}

func (d *directory) Rename(dstparent fs.Directory, src, dst string) error {
	d.fs.Lock()
	defer d.fs.Unlock()
	if d.fs.unmounted {
		return fs.ErrUnmounted
	}

	switch dstparent := dstparent.(type) {
	case *directory:
		if d.closed || dstparent.closed {
			return fs.ErrNotOpen
		}
		return rename(d.node, dstparent.node, src, dst)
	default:
		return fs.ErrInvalidArgs
	}
}

func (d *directory) Sync() error {
	d.fs.RLock()
	defer d.fs.RUnlock()
	if d.fs.unmounted {
		return fs.ErrUnmounted
	}
	d.RLock()
	defer d.RUnlock()
	if d.closed {
		return fs.ErrNotOpen
	}

	return syncDirectory(d.node)
}

func (d *directory) Unlink(target string) error {
	d.fs.RLock()
	defer d.fs.RUnlock()
	if d.fs.unmounted {
		return fs.ErrUnmounted
	}
	d.RLock()
	defer d.RUnlock()
	if d.closed {
		return fs.ErrNotOpen
	}

	return unlink(d.node, target)
}
