package vfs

import (
	"context"
	"os"
	"time"

	"gitlink.org.cn/cloudream/jcs-pub/client/internal/mount/fuse"
	"gitlink.org.cn/cloudream/jcs-pub/client/internal/mount/vfs/cache"
)

type FusePackage struct {
	vfs     *Vfs
	bktName string
	pkgName string
	modTime time.Time
	perm    os.FileMode
}

func newPackageFromCache(cache cache.CacheEntryInfo, vfs *Vfs) fuse.FsDir {
	pathComps := cache.PathComps
	return &FusePackage{
		vfs:     vfs,
		bktName: pathComps[0],
		pkgName: pathComps[1],
		modTime: cache.ModTime,
		perm:    cache.Perm,
	}
}

func (r *FusePackage) PathComps() []string {
	return []string{r.bktName, r.pkgName}
}

func (r *FusePackage) Name() string {
	return r.pkgName
}

func (r *FusePackage) Size() int64 {
	return 0
}

func (r *FusePackage) Perm() os.FileMode {
	return r.perm
}

func (r *FusePackage) ModTime() time.Time {
	return r.modTime
}

func (r *FusePackage) IsDir() bool {
	return true
}

func (r *FusePackage) SetModTime(time time.Time) error {
	dir := r.loadCacheDir()
	if dir == nil {
		return fuse.ErrNotExists
	}

	return dir.SetModTime(time)
}

// 如果不存在，应该返回ErrNotExists
func (r *FusePackage) Child(ctx context.Context, name string) (fuse.FsEntry, error) {
	return child(r.vfs, ctx, r, name)
}

func (r *FusePackage) Children(ctx context.Context) ([]fuse.FsEntry, error) {
	return listChildren(r.vfs, ctx, r)
}

func (r *FusePackage) ReadChildren() (fuse.DirReader, error) {
	ens, err := listChildren(r.vfs, context.Background(), r)
	if err != nil {
		return nil, err
	}

	return newFuseDirReader(ens), nil
}

func (r *FusePackage) NewDir(ctx context.Context, name string) (fuse.FsDir, error) {
	return newDir(r.vfs, ctx, name, r)
}

func (r *FusePackage) NewFile(ctx context.Context, name string, flags uint32) (fuse.FileHandle, uint32, error) {
	return newFile(r.vfs, ctx, name, r, flags)
}

func (r *FusePackage) RemoveChild(ctx context.Context, name string) error {
	return removeChild(r.vfs, ctx, name, r)
}

func (r *FusePackage) MoveChild(ctx context.Context, oldName string, newName string, newParent fuse.FsDir) error {
	return moveChild(r.vfs, ctx, oldName, r, newName, newParent.(FuseNode))
}

func (r *FusePackage) loadCacheDir() *cache.CacheDir {
	var createOpt *cache.CreateDirOption
	pkg, err := r.vfs.db.Package().GetByFullName(r.vfs.db.DefCtx(), r.bktName, r.pkgName)
	if err == nil {
		createOpt = &cache.CreateDirOption{
			ModTime: pkg.CreateTime,
		}
	}

	return r.vfs.cache.LoadDir([]string{r.bktName, r.pkgName}, createOpt)
}

var _ fuse.FsDir = (*FusePackage)(nil)
var _ FuseNode = (*FusePackage)(nil)
