//go:build linux || (darwin && amd64)

package fuse

import (
	"context"
	"syscall"

	fusefs "github.com/hanwen/go-fuse/v2/fs"
	"github.com/hanwen/go-fuse/v2/fuse"
)

type NodeBase struct {
	fusefs.Inode
	fs *Fuse
}

// Statfs implements statistics for the filesystem that holds this
// Inode. If not defined, the `out` argument will zeroed with an OK
// result.  This is because OSX filesystems must Statfs, or the mount
// will not work.
func (n *NodeBase) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno {
	const blockSize = 4096

	stats := n.fs.fs.Stats()

	// total, _, free := n.fsys.fs.Statfs()
	out.Blocks = uint64(stats.TotalDataBytes) / blockSize // Total data blocks in file system.
	out.Bfree = 1e9                                       // Free blocks in file system.
	out.Bavail = out.Bfree                                // Free blocks in file system if you're not root.
	out.Files = uint64(stats.TotalObjectCount)            // Total files in file system.
	out.Ffree = 1e9                                       // Free files in file system.
	out.Bsize = blockSize                                 // Block size
	out.NameLen = 255                                     // Maximum file name length?
	out.Frsize = blockSize                                // Fragment size, smallest addressable data size in the file system.
	return 0
}

// Getxattr should read data for the given attribute into
// `dest` and return the number of bytes. If `dest` is too
// small, it should return ERANGE and the size of the attribute.
// If not defined, Getxattr will return ENOATTR.
func (n *NodeBase) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
	return 0, syscall.ENOSYS // we never implement this
}

var _ fusefs.NodeGetxattrer = (*NodeBase)(nil)

// Setxattr should store data for the given attribute.  See
// setxattr(2) for information about flags.
// If not defined, Setxattr will return ENOATTR.
func (n *NodeBase) Setxattr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno {
	return syscall.ENOSYS // we never implement this
}

var _ fusefs.NodeSetxattrer = (*NodeBase)(nil)

// Removexattr should delete the given attribute.
// If not defined, Removexattr will return ENOATTR.
func (n *NodeBase) Removexattr(ctx context.Context, attr string) syscall.Errno {
	return syscall.ENOSYS // we never implement this
}

var _ fusefs.NodeRemovexattrer = (*NodeBase)(nil)

// Listxattr should read all attributes (null terminated) into
// `dest`. If the `dest` buffer is too small, it should return ERANGE
// and the correct size.  If not defined, return an empty list and
// success.
func (n *NodeBase) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) {
	return 0, syscall.ENOSYS // we never implement this
}

var _ fusefs.NodeListxattrer = (*NodeBase)(nil)
