package store

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
	"strings"
	"time"

	"github.com/klauspost/compress/zstd"
)

type FileStatus struct {
	FileName       string    `json:"fileName"`
	FilePath       string    `json:"filePath"`
	CreateTime     time.Time `json:"createTime"`
	FileMd5        string    `json:"fileMd5"`
	TransferStatus bool      `json:"transferStatus"`
}

// PathExists 判断所给路径文件/文件夹是否存在
func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	//IsNotExist来判断，是不是不存在的错误
	if os.IsNotExist(err) { //如果返回的错误类型使用os.isNotExist()判断为true，说明文件或者文件夹不存在
		return false, nil
	}
	return false, err //如果有错误了，但是不是不存在的错误，所以把这个错误原封不动的返回
}

func Load(storePath string, list map[string]*FileStatus) error {
	if b, _ := PathExists(storePath); !b {
		_ = os.MkdirAll(storePath, os.ModePerm)
	}
	fileName := strings.Replace(storePath, ":\\", "_", -1)
	fileName = strings.Replace(storePath, "\\", "_", -1)
	fileName = strings.Replace(storePath, "/", "_", -1)
	storeFile := path.Join(storePath, fmt.Sprintf("%s.hdb", fileName))
	if b, _ := PathExists(storeFile); !b {
		NewFile(storeFile)
		return nil
	}
	f, _ := os.OpenFile(storeFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	defer func(f *os.File) {
		_ = f.Close()
	}(f)
	buff, err := io.ReadAll(f)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	if len(buff) > 0 {
		str, err := UnCompress(buff)
		if err != nil {
			return err
		}
		err = json.Unmarshal(str, &list)
		if err != nil {
			return err
		}
	}
	return nil
}

func Save(storePath string, list map[string]*FileStatus) {
	if b, _ := PathExists(storePath); !b {
		_ = os.MkdirAll(storePath, os.ModePerm)
	}
	fileName := strings.Replace(storePath, ":\\", "_", -1)
	fileName = strings.Replace(storePath, "\\", "_", -1)
	fileName = strings.Replace(storePath, "/", "_", -1)
	storeFile := path.Join(storePath, fmt.Sprintf("%s.hdb", fileName))
	if b, _ := PathExists(storeFile); !b {
		NewFile(storeFile)
	}
	f, _ := os.OpenFile(storeFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
	defer func() {
		_ = f.Close()
	}()
	str, _ := json.Marshal(list)
	c := Compress(str)
	_, _ = f.Write(c)
}
func NewFile(fileName string) {
	f, _ := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
	defer func(f *os.File) {
		_ = f.Close()
	}(f)
}

// Compress 压缩
func Compress(src []byte) []byte {
	encoder, _ := zstd.NewWriter(nil)
	zstd.WithEncoderConcurrency(3)
	return encoder.EncodeAll(src, make([]byte, 0, len(src)))
}

func UnCompress(src []byte) ([]byte, error) {
	d, err := zstd.NewReader(nil)
	if err != nil {
		return nil, err
	}
	defer d.Close()

	uncompressed, err := d.DecodeAll(src, nil)
	if err != nil {
		return nil, err
	}

	return uncompressed, nil
}
