package interceptor

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

type FileModule struct{}

func (f *FileModule) ReadFile(path string, encode string) interface{} {
	fileContent, err := os.ReadFile(path)
	if err != nil {
		panic(err)
	}
	if encode == "binary" {
		return fileContent
	}
	return string(fileContent)
}

func (f *FileModule) WriteFile(path string, content interface{}, encode string) {
	fileContent, err := os.ReadFile(path)
	if err != nil {
		panic(err)
	}
	if encode == "binary" {
		os.WriteFile(path, fileContent, 0644)
	}
	os.WriteFile(path, []byte(content.(string)), 0644)
}

func (f *FileModule) RemoveFile(path string) {
	os.Remove(path)
}

func (f *FileModule) Exists(path string) bool {
	_, err := os.Stat(path)
	if err != nil {
		return os.IsExist(err)
	}
	return true
}

func (f *FileModule) IsDir(path string) bool {
	fileInfo, err := os.Stat(path)
	if err != nil {
		return false
	}
	return fileInfo.IsDir()
}

func (f *FileModule) MakeDir(path string, rescursive bool) {
	os.MkdirAll(path, 0755)
}

func (f *FileModule) RemoveDir(path string) {
	os.RemoveAll(path)
}

func (f *FileModule) ListDir(path string) []string {
	files, err := os.ReadDir(path)
	if err != nil {
		return nil
	}
	fileNames := make([]string, 0, len(files))
	for _, file := range files {
		fileNames = append(fileNames, file.Name())
	}
	return fileNames
}

func (f *FileModule) Copy(src, dst string) {
	if !f.IsDir(dst) {
		if f.IsDir(filepath.Dir(dst)) {
			bcontent := f.ReadFile(src, "binary")
			f.WriteFile(dst, bcontent, "binary")
			return
		} else {
			panic(fmt.Errorf("destination directory not exists"))
		}

	}
	if f.IsDir(src) {
		if strings.HasSuffix(dst, "/") {
			dst = dst + filepath.Base(src)
			f.MakeDir(dst, true)
		}
		os.CopyFS(dst, os.DirFS(src))
	}
	// 文件拷贝, 需要先读取文件内容, 然后写入到目标文件中
	bcontent := f.ReadFile(src, "binary")
	f.WriteFile(dst, bcontent, "binary")
	// 拷贝文件属性
	fileInfo, err := os.Stat(src)
	if err != nil {
		panic(err)
	}
	os.Chmod(dst, fileInfo.Mode())
	os.Chtimes(dst, fileInfo.ModTime(), fileInfo.ModTime())
}
