package gamedata

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strconv"

	"server/conf"
	"server/game/mod/item"
	"server/pkg/github.com/name5566/leaf/log"
	"server/pkg/github.com/name5566/leaf/recordfile"

	"github.com/fsnotify/fsnotify"
)

var watcher *fsnotify.Watcher
var ConfPath = "./gamedata/config/"

func init() {
	if conf.Server.GameConfPath != "" {
		ConfPath = conf.Server.GameConfPath
	}
	watcher, _ = fsnotify.NewWatcher()
	watcher.Add(ConfPath + "reload")
	go func() {
		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					return
				}
				if event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Create == fsnotify.Create || event.Op&fsnotify.Rename == fsnotify.Rename {
					for k := range G_AllConfigsJsonData {
						InitCfg(k)
						log.Debug("配置已重新加载:%s", k)
					}

				}
			case err, ok := <-watcher.Errors:
				if !ok {
					return
				}
				fmt.Println("错误:", err)
			}
		}
	}()

}

func Reload() {
	for k := range G_AllConfigsJsonData {
		InitCfg(k)
		log.Debug("配置已重新加载:%s", k)
	}
}

func readRfNew(st interface{}, ralativePath string) *recordfile.RecordFile {
	rf, err := recordfile.New(st)
	if err != nil {
		log.Fatal("%v", err)
	}
	fn := ralativePath + ".txt"
	err = rf.Read(ConfPath + fn)
	if err != nil {
		log.Fatal("%v: %v", fn, err)
	}

	return rf
}

func InitCfg(cfgname string) {
	// 读取文件内容
	filePath := ConfPath + cfgname + ".json"
	absPath, _ := filepath.Abs(filePath)

	file, err := os.Open(absPath)
	if err != nil {
		log.Debug("打开文件失败:%v", err)
		return
	}
	defer file.Close()

	// 读取文件内容到字节数组
	byteValue, err := io.ReadAll(file)
	if err != nil {
		log.Debug("读取文件失败:%v", err)
		return
	}
	var data map[string]interface{}
	// 反序列化JSON数据
	err = json.Unmarshal(byteValue, &data)
	if err != nil {
		log.Debug("反序列化失败:%v", err)
		return
	}
	rf := new(ConfigData)
	convertedData := make(map[string]interface{})
	for k, v := range data {
		convertedData[k] = v
	}
	rf.SetData(convertedData)
	G_AllConfigsJsonData[cfgname] = rf
}

func GetValue(a interface{}, key string) interface{} {
	if a == nil {
		return nil
	}
	if v, ok := a.(map[string]interface{})[key]; ok {
		return v
	}
	return nil
}

func GetIntValue(a interface{}, key string) int {
	if a == nil {
		return 0
	}
	if v, ok := a.(map[string]interface{})[key]; ok {
		if v == nil {
			return 0
		}
		return int(v.(float64))
	}
	return 0
}

func GetIntSliceValue(a interface{}, key string) []int {
	if a == nil {
		return nil
	}
	if v, ok := a.(map[string]interface{})[key]; ok {
		if v == nil {
			return nil
		}
		var r []int
		for _, v := range v.([]interface{}) {
			r = append(r, int(v.(float64)))
		}
		return r
	}
	return nil
}

func GetFloatValue(a interface{}, key string) float64 {
	if a == nil {
		return 0
	}
	if v, ok := a.(map[string]interface{})[key]; ok {
		if v == nil {
			return 0
		}
		return v.(float64)
	}
	return 0
}

func GetItemList(a interface{}, key string) []*item.Item {
	if a == nil {
		return nil
	}
	if v, ok := a.(map[string]interface{})[key]; ok {
		if v == nil {
			return nil
		}
		return item.ParseItem(v)
	}
	return nil
}

func GetStringValue(a interface{}, key string) string {
	if a == nil {
		return ""
	}
	if v, ok := a.(map[string]interface{})[key]; ok {
		if v == nil {
			return ""
		}
		return v.(string)
	}
	return ""
}

func GetData(cfgname string) (map[string]interface{}, error) {
	if v, ok := G_AllConfigsJsonData[cfgname]; ok {
		return v.GetData(), nil
	}
	return make(map[string]interface{}), errors.New("not found")
}

func GetDataByKey(cfgname, key string) (map[string]interface{}, error) {
	if v, ok := G_AllConfigsJsonData[cfgname]; ok {
		if v, ok := v.GetData()[key]; ok {
			return v.(map[string]interface{}), nil
		}
	}
	return make(map[string]interface{}), errors.New("not found")
}

func GetDataByIntKey(cfgname string, key int) (map[string]interface{}, error) {
	keyStr := strconv.Itoa(key)
	if v, ok := G_AllConfigsJsonData[cfgname]; ok {
		if v, ok := v.GetData()[keyStr]; ok {
			return v.(map[string]interface{}), nil
		}
	}
	return make(map[string]interface{}), errors.New("not found")
}
