// 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 (
	"time"

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

func closeFile(n node.FileNode) error {
	doClose := true
	return flushFile(n, doClose)
}

func closeDirectory(n node.DirectoryNode, unmount bool) error {
	n.Lock()
	defer n.Unlock()
	err := n.RefDown(1)
	n.Metadata().Dcache.Release(n.ID())
	return err
}

func stat(n node.Node) (int64, time.Time, time.Time, error) {
	n.RLock()
	defer n.RUnlock()
	return n.Size(), time.Time{}, n.MTime(), nil
}

func touch(n node.Node, lastAccess, lastModified time.Time) {
	n.Lock()
	defer n.Unlock()
	n.SetMTime(direntry.ModifyTime(lastModified))
}

func dup(n node.Node) {
	metadata := n.Metadata()
	if n.IsDirectory() {
		metadata.Dcache.Acquire(n.(node.DirectoryNode).ID())
	} else {
		parent, _ := n.(node.FileNode).LockParent()
		if parent != nil {
			// If we have a parent, ACQUIRE a reference to it.
			metadata.Dcache.Acquire(parent.ID())
			parent.Unlock()
		}
	}

	n.Lock()
	n.RefUp()
	n.Unlock()
}

func readDir(n node.DirectoryNode) ([]fs.Dirent, error) {
	n.RLock()
	defer n.RUnlock()

	var result []fs.Dirent
	if n.IsRoot() {
		// The root directory does not contain ".". Create this fake entry.
		dot := direntry.New(".", 0, fs.FileTypeDirectory)
		dot.WriteTime = n.MTime()
		result = append(result, dot)
	}

	for i := 0; ; {
		entry, numSlots, err := node.Read(n, i)
		if err != nil {
			return nil, err
		}

		if entry.IsLastFree() {
			break
		} else if !entry.IsFree() && entry.GetName() != ".." {
			result = append(result, entry)
		}
		i += numSlots
	}
	return result, nil
}

func open(n node.DirectoryNode, name string, flags fs.OpenFlags) (node.Node, error) {
	if n.IsDeleted() {
		return nil, fs.ErrFailedPrecondition
	}

	// ACQUIRE parent directory from dcache.
	// After this function succeeds, we'll need to be sure to RELEASE "parent" before returning.
	parent, singleName, mustBeDir, err := traversePath(n, name)
	if err != nil { // Parent directory containing "name" cannot be resolved
		return nil, err
	}

	if mustBeDir {
		flags |= fs.OpenFlagDirectory
	}

	// Helper function to validate the flags when opening files via "." or "..".
	validateDotFlags := func(flags fs.OpenFlags) error {
		if flags.Create() || flags.Exclusive() {
			return fs.ErrInvalidArgs // Node already exists; these are bad arguments
		} else if flags.Append() || flags.Truncate() || flags.File() {
			return fs.ErrNotAFile // File-specific args
		} else if !flags.Read() && !flags.Path() {
			return fs.ErrPermission // Directories require read privileges
		}
		return nil
	}

	switch singleName {
	case ".":
		if err = validateDotFlags(flags); err != nil {
			n.Metadata().Dcache.Release(parent.ID())
			return nil, err
		}
		parent.Lock()
		parent.RefUp()
		parent.Unlock()
		// We don't need to RELEASE the dcache reference to the parent directory, since we're
		// opening that node anyway.
		return parent, nil
	case "..":
		return nil, fs.ErrNotSupported
	}

	// Either "openIncremental" or "createIncremental" will ACQUIRE the target from the dcache
	// if it is a directory.
	openedNode, err := func() (node.Node, error) {
		parent.Lock() // Read from the parent; potentially open a child.
		defer parent.Unlock()
		defer n.Metadata().Dcache.Release(parent.ID())
		openedNode, err := openIncremental(parent, singleName, flags)
		if err == fs.ErrNotFound {
			// If we could not open the file/directory because it doesn't exist, try creating it.
			openedNode, err = createIncremental(parent, singleName, flags)
		}
		if err != nil {
			return nil, err
		}
		return openedNode, nil
	}()
	if err != nil {
		return nil, err
	}

	// Thanks to {traverse,create}Incremental, we know that openedNode exists in the dcache (if it
	// is a directory). Increase the external refcount, and possibly truncate.
	openedNode.Lock()
	defer openedNode.Unlock()
	openedNode.RefUp()
	if flags.Truncate() {
		openedNode.SetSize(0)
	}
	return openedNode, nil
}

// Renames a file or directory to a new location.
// Currently, only supports a single-threaded version which locks the entire filesystem.
func rename(srcStart node.DirectoryNode, dstStart node.DirectoryNode, src, dst string) error {
	metadata := srcStart.Metadata()
	srcParent, srcName, srcMustBeDir, err := traversePath(srcStart, src) // ACQUIRE srcParent...
	if err != nil {
		return err
	}
	defer metadata.Dcache.Release(srcParent.ID()) // ... ensure it is RELEASED

	// Verify that src is valid, independent of dst
	if srcName == "." || srcName == ".." {
		return fs.ErrIsActive
	}
	dstParent, dstName, dstMustBeDir, err := traversePath(dstStart, dst) // ACQUIRE dstParent...
	if err != nil {
		return err
	}
	defer metadata.Dcache.Release(dstParent.ID()) // ... ensure it is RELEASED

	srcFlags := fs.OpenFlagRead
	if srcMustBeDir || dstMustBeDir {
		srcFlags |= fs.OpenFlagDirectory
	}
	srcEntry, srcDirentryIndex, err := lookupAndCheck(srcParent, srcName, srcFlags)
	if err != nil {
		return err
	} else if srcEntry == nil {
		return fs.ErrNotFound
	}

	// Verify that dst is valid, independent of src
	if dstName == "." || dstName == ".." {
		return fs.ErrIsActive
	}
	// If dst is src (same directory, same name), end early.
	if srcParent.ID() == dstParent.ID() && srcName == dstName {
		return nil
	}

	// If we are moving a directory to a new directory dst...
	if srcParent.ID() != dstParent.ID() && srcEntry.GetType() == fs.FileTypeDirectory {
		// ... Verify that dst is not a subdirectory of src.
		// Call this code as an anonymous function to make it easier to stack deferred calls to
		// RELEASE traversed directories.
		if err := func(srcEntry *direntry.Dirent, observedNode node.DirectoryNode) error {
			for !observedNode.IsRoot() {
				if observedNode.StartCluster() == srcEntry.Cluster {
					// Cannot rename src into a subdirectory of itself
					return fs.ErrInvalidArgs
				}
				parentEntry, _, err := node.Lookup(observedNode, "..")
				if err != nil {
					return err
				}
				// ACQUIRE a new observed node...
				observedNode, err = metadata.Dcache.CreateOrAcquire(metadata, parentEntry.Cluster, parentEntry.WriteTime)
				if err != nil {
					return err
				}
				defer metadata.Dcache.Release(observedNode.ID()) // ... ensure it is RELEASED
			}
			return nil
		}(srcEntry, dstParent); err != nil {
			return err
		}
	}

	// Begin modification of the on-disk directory structures.
	// Since this process is tricky, if we have already begun modification but encountered an
	// unexpected error, the entire filesystem should be either (1) unmounted or (2) altered to
	// readonly mode.

	// Does the destination already exist?
	dstEntry, dstDirentryIndex, err := node.Lookup(dstParent, dstName)
	if err != nil {
		return err
	}
	if dstEntry == nil {
		// Destination DOES NOT exist. Create an updated srcEntry (new name)
		newSrcEntry := direntry.New(dstName, srcEntry.Cluster, srcEntry.GetType())
		newSrcEntry.Size = srcEntry.Size
		srcEntry = newSrcEntry

		// Add src to new dst
		dstDirentryIndex, err = node.Allocate(dstParent, srcEntry)
		if err != nil {
			return err
		}
	} else {
		dstFlags := fs.OpenFlagRead
		if dstMustBeDir {
			dstFlags |= fs.OpenFlagDirectory
		}

		// Destination DOES exist. We should unlink and replace it.
		if dstEntry.GetType() != srcEntry.GetType() {
			return fs.ErrNotADir
		}
		_, isDir, err := ensureCanUnlink(dstParent, dstName, dstFlags)
		if err != nil {
			return err
		}
		oldCluster, err := doReplace(dstParent, dstDirentryIndex, isDir, srcEntry.Cluster, srcEntry.WriteTime, srcEntry.Size)
		if err != nil {
			return err
		}
		// Even if we struggle to free the old cluster, we've already replaced the destination
		// direntry.
		metadata.ClusterMgr.ClusterDelete(oldCluster)
	}

	if (srcEntry.GetType() == fs.FileTypeDirectory) && (srcParent != dstParent) {
		// If src is a directory, and it is moving to a new parent, update src's ".."
		// ACQUIRE the srcEntry...
		srcNode, err := metadata.Dcache.CreateOrAcquire(metadata, srcEntry.Cluster, srcEntry.WriteTime)
		if err != nil {
			panic(err)
		} else if err := node.WriteDotAndDotDot(srcNode, srcEntry.Cluster, dstParent.StartCluster()); err != nil {
			panic(err)
		}
		metadata.Dcache.Release(srcNode.ID()) // ... ensure it is RELEASED
	}

	// Remove src from the srcParent
	if _, err = node.Free(srcParent, srcDirentryIndex); err != nil {
		panic(err)
	} else if srcNode, ok := srcParent.ChildFile(srcDirentryIndex); ok {
		// If the source is an open file, relocate it.
		srcNode.MoveFile(dstParent, dstDirentryIndex)
		metadata.Dcache.Transfer(srcParent.ID(), dstParent.ID(), srcNode.RefCount())
	}

	return nil
}

func syncFile(n node.FileNode) error {
	doClose := false
	flushFile(n, doClose)
	n.Metadata().Dev.Flush()
	return nil
}

func syncDirectory(n node.DirectoryNode) error {
	n.Metadata().Dev.Flush()
	return nil
}

func unlink(n node.DirectoryNode, target string) error {
	parent, name, mustBeDir, err := traversePath(n, target) // ACQUIRE parent...
	if err != nil {
		return err
	}
	defer n.Metadata().Dcache.Release(parent.ID()) // ... ensure it is RELEASED
	flags := fs.OpenFlagRead
	if mustBeDir {
		flags |= fs.OpenFlagDirectory
	}

	// Use an anonymous function for the duration of holding a lock on the parent.
	cluster, err := func() (uint32, error) {
		parent.Lock()
		defer parent.Unlock()
		// Ensure that we are not attempting to unlink a non-empty directory
		direntryIndex, isDir, err := ensureCanUnlink(parent, name, flags)
		if err != nil {
			return 0, err
		}
		// The target dirent exists, and is in an unlinkable state.
		cluster, err := doUnlink(parent, direntryIndex, isDir)
		if err != nil {
			return 0, err
		}
		return cluster, nil
	}()

	if err != nil {
		return err
	}
	return parent.Metadata().ClusterMgr.ClusterDelete(cluster)
}

// Sync the file with its parent directory. If requested, decrease the number of references to the
// file.
//
// Precondition:
//	 - the node lock is not held by the caller
//	 - the parent lock is not held by the caller
// Postcondition:
//	 - same as precondition
func flushFile(n node.FileNode, doClose bool) (err error) {
	// Lock parent (if not nil) then node
	parent, direntIndex := n.LockParent()
	n.Lock()

	if parent != nil {
		// If this node has a direntry which can be updated, update it
		if !n.Metadata().Readonly {
			if _, err = node.Update(parent, n.StartCluster(), n.MTime(), uint32(n.Size()), direntIndex); err != nil {
				panic(err)
			}
		}
		if doClose {
			// We are about to "ref down" the child. If it is the LAST child, remove it from the parent.
			if n.RefCount() == 1 {
				parent.RemoveFile(direntIndex)
			}

			// RELEASE the parent directory from the access acquired when opening
			parent.Metadata().Dcache.Release(parent.ID())
		}

		// Unlock the parent after updating the dirent, but before possibly deleting the child's
		// clusters. This is fine because (1) the parent is not updated beyond this point, and (2)
		// the lock acquisition order is preserved, so deadlock is prevented.
		parent.Unlock()
	}

	if doClose {
		err = n.RefDown(1)
	}
	n.Unlock()
	return err
}

// Ensure that we are not attempting to unlink a non-empty directory by looking up the name of a
// file/directory in the parent. Also returns the direntryIndex of the child.
//
// Precondition:
//	 - parent is locked
//	 - the node lock corresponding to 'name' is not held by the caller
// Postcondition:
//	 - parent is locked
func ensureCanUnlink(parent node.DirectoryNode, name string, flags fs.OpenFlags) (index int, isdir bool, err error) {
	if name == "." || name == ".." {
		return 0, true, fs.ErrIsActive
	}

	entry, direntryIndex, err := lookupAndCheck(parent, name, flags)
	if err != nil {
		return 0, false, err
	}

	if entry.GetType() == fs.FileTypeDirectory {
		// ACQUIRE openedDir...
		openedDir, err := traverseDirectory(parent, name, fs.OpenFlagRead|fs.OpenFlagDirectory)
		if err != nil {
			return 0, true, err
		}
		defer parent.Metadata().Dcache.Release(openedDir.ID()) // ... ensure it is RELEASED

		openedDir.RLock()
		defer openedDir.RUnlock()
		if empty, err := node.IsEmpty(openedDir); err != nil {
			return 0, true, err
		} else if !empty {
			// Cannot delete non-empty directories. As long as the parent remains locked until
			// 'unlink' is complete, the child directory cannot become non-empty (it's closed).
			return 0, true, fs.ErrNotEmpty
		}
	}
	return direntryIndex, entry.GetType() == fs.FileTypeDirectory, nil
}

// Update the in-memory connection between a parent and a child to signify that the child should be
// removed from the parent and deleted.
// Does not modify direntries -- exclusively in-memory.
// Returns true if child file is open.
//
// Precondition:
//	 - parent is locked
//	 - child lock is not held by the caller
// Postcondition:
//	 - parent is locked
func nodeDeleteChildFile(parent node.DirectoryNode, direntryIndex int) bool {
	if child, ok := parent.ChildFile(direntryIndex); ok {
		// RELEASE the parent directory from the access acquired when opening
		parent.Metadata().Dcache.Release(parent.ID())
		child.Lock()
		defer child.Unlock()
		parent.RemoveFile(direntryIndex)
		child.MarkDeleted()
		child.RefDown(0)
		return true
	}
	return false
}

// nodeDeleteChildDir acts like nodeDeleteChildFile, but acts
// on directories instead.
func nodeDeleteChildDir(parent node.DirectoryNode, id uint32) bool {
	if child, err := parent.Metadata().Dcache.Lookup(id); err == nil {
		child.Lock()
		defer child.Unlock()
		child.MarkDeleted()
		child.RefDown(0)
		// RELEASE the parent directory from the access acquired when opening
		parent.Metadata().Dcache.Release(id)
		return true
	}
	return false
}

// Replace the direntry at index "direntryIndex" with the node "replacement".
// Returns the replaced cluster which should be deleted, if any.
//
// Precondition:
//	 - parent is locked
//	 - the node lock corresponding to 'direntryIndex' is not held by the caller
// Postcondition:
//	 - parent is locked
//	 - the dirent corresponding to 'direntryIndex' is replaced with an entry for 'replacement'
//	 - the node corresponding to 'direntryIndex' is marked as deleted (if open)
func doReplace(parent node.DirectoryNode, direntryIndex int, isDir bool, cluster uint32, writeTime time.Time, size uint32) (uint32, error) {
	oldCluster, err := node.Update(parent, cluster, writeTime, size, direntryIndex)
	if err != nil {
		return 0, err
	}
	if isDir {
		if childOpen := nodeDeleteChildDir(parent, oldCluster); !childOpen {
			// Return the child's cluster for deleting if it is not open
			return oldCluster, nil
		}
	} else {
		if childOpen := nodeDeleteChildFile(parent, direntryIndex); !childOpen {
			// Return the child's cluster for deleting if it is not open
			return oldCluster, nil
		}

	}
	return 0, nil // The cluster will be deleted when the child file is closed
}

// Remove the direntry at index "direntryIndex" in the parent node.
// Returns the cluster which should be deleted.
//
// Precondition:
//	 - parent is locked
//	 - the node lock corresponding to 'direntryIndex' is not held by the caller
// Postcondition:
//	 - parent is locked
//	 - dirent is removed from the directory
//	 - the node corresponding to 'direntryIndex' is marked as deleted (if open)
func doUnlink(parent node.DirectoryNode, direntryIndex int, isDir bool) (uint32, error) {
	// Remove the dirent from the directory. The node is not yet deleted.
	entry, err := node.Free(parent, direntryIndex)
	if err != nil {
		return 0, err
	}

	if isDir {
		if childOpen := nodeDeleteChildDir(parent, entry.Cluster); !childOpen {
			// Return the child's cluster for deleting if it is not open
			return entry.Cluster, nil
		}
	} else {
		if childOpen := nodeDeleteChildFile(parent, direntryIndex); !childOpen {
			// Return the child's cluster for deleting if it is not open
			return entry.Cluster, nil
		}

	}

	return 0, nil // The cluster will be deleted when the child file is closed
}

// Given a direntry and a parent directory, create a node representing the child.
//
// Precondition:
//	 - parent is locked
// Postcondition:
//	 - parent is locked
//	 - If successful, the parent node is ACQUIRED (ref++) in the dcache
func openFileFromDirent(parent node.DirectoryNode, index int, dirent *direntry.Dirent) (node.FileNode, error) {
	// Look up the file node in the local map of children
	if child, ok := parent.ChildFile(index); ok {
		parent.Metadata().Dcache.Acquire(parent.ID())
		return child, nil
	}

	// Child is not open. Add to parent.
	child, err := node.NewFile(parent.Metadata(), parent, index, dirent.Cluster, dirent.WriteTime)
	if err != nil {
		return nil, err
	}
	// Set the size exactly -- it is recorded in the direntry referring to this file
	child.SetSize(int64(dirent.Size))

	// ACQUIRE dcache access to the parent node, since we need it when we update the file's
	// direntry. This access is RELEASED in the following circumstances:
	// 1) File is unlinked
	// 2) File is closed
	// 3) File is renamed
	parent.Metadata().Dcache.Acquire(parent.ID())
	return child, nil
}

// Opens a single node WITHOUT path resolution.
//
// Precondition:
//	 - parent is locked
// Postcontidion:
//	 - parent is locked
//	 - If the opened node is a directory, it is ACQUIRED in the dcache
func openIncremental(parent node.DirectoryNode, name string, flags fs.OpenFlags) (node.Node, error) {
	if name == "." || name == ".." {
		return traverseDirectory(parent, name, flags)
	}
	// Check that the path already exists with the requested name
	entry, direntryIndex, err := lookupAndCheck(parent, name, flags)
	if err != nil {
		return nil, err
	} else if entry.GetType() == fs.FileTypeDirectory {
		return parent.Metadata().Dcache.CreateOrAcquire(parent.Metadata(), entry.Cluster, entry.WriteTime)
	}
	return openFileFromDirent(parent, direntryIndex, entry)
}

// Creates a single node WITHOUT path resolution.
//
// Precondition:
//	 - parent is locked
// Postcondition:
//	 - parent is locked
//	 - If the created node is a directory, it is ACQUIRED in the dcache
func createIncremental(parent node.DirectoryNode, name string, flags fs.OpenFlags) (node.Node, error) {
	// File / Directory does not exist...
	if !flags.Create() {
		return nil, fs.ErrNotFound // If we aren't creating anything, we didn't find our file
	} else if flags.File() && !flags.Write() {
		return nil, fs.ErrPermission // Creating a file requires write permssions
	} else if flags.File() == flags.Directory() {
		return nil, fs.ErrInvalidArgs // We must know if we're creating a file or directory
	} else if name == "." || name == ".." {
		return nil, fs.ErrInvalidArgs
	}
	// ... but the flags identify we should create it.

	// TODO(smklein): Should we be checking readonly permissions here? The cluster manager also has
	// a readonly flag, and will fail appropriately, but still. If anything, shouldn't "Readonly" be
	// applied at a block shim layer? That would make it easier to "flip on readonly" in case of
	// tragic error.

	if flags.File() {
		entry := direntry.New(name, 0, fs.FileTypeRegularFile)
		direntryIndex, err := node.Allocate(parent, entry)
		if err != nil {
			return nil, err
		}
		child, err := openFileFromDirent(parent, direntryIndex, entry)
		if err != nil {
			panic(err)
		}
		return child, nil
	}

	if flags.Append() || flags.Truncate() {
		return nil, fs.ErrNotAFile // Reject non-directory flags
	} else if !flags.Read() && !flags.Path() {
		return nil, fs.ErrPermission // Directories require read permission
	}

	// Create / Open the child directory -- it's in a weird state right now, since it's totally empty.
	newCluster, err := parent.Metadata().ClusterMgr.ClusterExtend(0)
	if err != nil {
		return nil, err
	}

	// Add the new directory's direntry to the parent directory.
	entry := direntry.New(name, newCluster, fs.FileTypeDirectory)
	_, err = node.Allocate(parent, entry)
	if err != nil {
		parent.Metadata().ClusterMgr.ClusterDelete(newCluster) // Free the cluster we just allocated.
		return nil, err
	}

	// Create the child directory and ACQUIRE it from the dcache.
	child, err := parent.Metadata().Dcache.CreateOrAcquire(parent.Metadata(), newCluster, clock.Now())
	if err != nil {
		panic("Unable to create new directory after allocating cluster")
	}

	child.Lock()
	defer child.Unlock()

	// "The dotdot entry points to the starting cluster of the parent directory..."
	parentCluster := parent.StartCluster()
	if parent.IsRoot() {
		// "... which is 0 if this directory's parent is the root directory"
		// - FAT: General Overview of On-Disk Format, Page 25
		parentCluster = 0
	}

	// Initialize the new child directory
	if err := node.WriteDotAndDotDot(child, newCluster, parentCluster); err != nil {
		panic(err)
	} else if err := node.MakeEmpty(child); err != nil {
		panic(err)
	}

	return child, nil
}
