package cache

import (
	"fmt"
	"os"
	"time"
)

type CacheDir struct {
	cache     *Cache
	pathComps []string
	name      string
	modTime   time.Time
	perm      os.FileMode
}

func createNewCacheDir(c *Cache, pathComps []string) (*CacheDir, error) {
	metaPath := c.GetCacheMetaPath(pathComps...)
	dataPath := c.GetCacheDataPath(pathComps...)

	err := os.MkdirAll(metaPath, 0755)
	if err != nil {
		return nil, err
	}

	err = os.MkdirAll(dataPath, 0755)
	if err != nil {
		return nil, err
	}

	// 修改文件夹的修改时间
	modTime := time.Now()
	os.Chtimes(dataPath, modTime, modTime)

	return &CacheDir{
		cache:     c,
		pathComps: pathComps,
		name:      pathComps[len(pathComps)-1],
		modTime:   modTime,
		perm:      0755,
	}, nil
}

func loadCacheDir(c *Cache, pathComps []string) (*CacheDir, error) {
	stat, err := os.Stat(c.GetCacheDataPath(pathComps...))
	if err != nil {
		return nil, err
	}

	if !stat.IsDir() {
		return nil, fmt.Errorf("not a directory")
	}

	return &CacheDir{
		cache:     c,
		pathComps: pathComps,
		name:      stat.Name(),
		modTime:   stat.ModTime(),
		perm:      stat.Mode().Perm(),
	}, nil
}

func makeCacheDirFromOption(c *Cache, pathComps []string, opt CreateDirOption) (*CacheDir, error) {
	metaPath := c.GetCacheMetaPath(pathComps...)
	dataPath := c.GetCacheDataPath(pathComps...)

	err := os.MkdirAll(metaPath, 0755)
	if err != nil {
		return nil, err
	}

	err = os.MkdirAll(dataPath, 0755)
	if err != nil {
		return nil, err
	}

	os.Chtimes(dataPath, opt.ModTime, opt.ModTime)
	return &CacheDir{
		cache:     c,
		pathComps: pathComps,
		name:      pathComps[len(pathComps)-1],
		modTime:   opt.ModTime,
		perm:      0755,
	}, nil
}

func loadCacheDirInfo(c *Cache, pathComps []string, dataFileInfo os.FileInfo) (*CacheEntryInfo, error) {
	return &CacheEntryInfo{
		PathComps: pathComps,
		Size:      0,
		Perm:      dataFileInfo.Mode(),
		ModTime:   dataFileInfo.ModTime(),
		IsDir:     true,
	}, nil
}

func (f *CacheDir) PathComps() []string {
	return f.pathComps
}

func (f *CacheDir) Name() string {
	return f.name
}

func (f *CacheDir) Size() int64 {
	return 0
}

func (f *CacheDir) Mode() os.FileMode {
	return f.perm | os.ModeDir
}

func (f *CacheDir) ModTime() time.Time {
	return f.modTime
}

func (f *CacheDir) IsDir() bool {
	return true
}

func (f *CacheDir) Info() CacheEntryInfo {
	return CacheEntryInfo{
		PathComps: f.pathComps,
		Size:      0,
		Perm:      f.perm,
		ModTime:   f.modTime,
		IsDir:     true,
	}
}

func (f *CacheDir) SetModTime(modTime time.Time) error {
	dataPath := f.cache.GetCacheDataPath(f.pathComps...)
	return os.Chtimes(dataPath, modTime, modTime)
}
