package srvdata

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

	"github.com/howeyc/fsnotify"

	"mongo.games.com/goserver/core"
	"mongo.games.com/goserver/core/basic"
	"mongo.games.com/goserver/core/logger"

	"mongo.games.com/game/model"
)

func IsLibFile(name string) bool {
	strArr := strings.Split(name, "_")
	if len(strArr) < 1 {
		return false
	}
	if strArr[0] == "LB" {
		return true
	} else {
		return false
	}
}

// DatFileModifiedCommand dat文件加载
type DatFileModifiedCommand struct {
	fileName string
}

func (fmc *DatFileModifiedCommand) Done(o *basic.Object) error {
	fn := filepath.Base(fmc.fileName)
	logger.Logger.Info("modified file name ======", fn)

	// loader
	loader := DataMgr.GetLoader(fn)
	if loader != nil {
		err := loader.Reload(fmc.fileName)
		if err != nil {
			logger.Logger.Warn(fn, " loader err:", err)
		}
	}
	// loaderAfter
	loaderAfter := DataMgrAfter.GetLoader(fn)
	if loaderAfter != nil {
		for _, v := range loaderAfter {
			err := v.Reload(fmc.fileName)
			if err != nil {
				logger.Logger.Warn(fn, " loaderAfter err:", err)
			}
		}
	}

	//todo 实现DataLoader
	switch fn {
	case "DB_ClientVer.dat":
		err := updateClientVers()
		if err != nil {
			return err
		}
	case "DB_Createroom.dat":
		CreateRoomMgrSington.Init()
	case "DB_Game_Drop.dat":
		GameDropMgrSington.Init()
	case "DB_Game_Role.dat", "DB_Game_Pet.dat":
		RolePetMgrSington.Init()
	}

	return nil
}

// JsonFileModifiedCommand json文件加载
type JsonFileModifiedCommand struct {
	fileName string
}

func (gmc *JsonFileModifiedCommand) Done(o *basic.Object) error {
	fn := filepath.Base(gmc.fileName)
	switch fn {
	case "gameparam.json":
		model.InitGameParam()
	case "gmac.json":
		model.InitGMAC()
	case "thrconfig.json":
		model.InitGameConfig()
	case "fishingparam.json":
		model.InitFishingParam()
	//case "bullfightparam.json":
	//	model.InitBullFightParam()
	//case "winthreeparam.json":
	//	model.InitWinThreeParam()
	//case "mahjongparam.json":
	//	model.InitMahJongParam()
	case "normalparam.json":
		model.InitNormalParam()
	case "clientparam.json":
		model.InitClientParam()
	}
	return nil
}

var Config = Configuration{}

type Configuration struct {
	RootPath string //文件目录
	LoadLib  bool   //是否装载牌库文件
	watcher  *fsnotify.Watcher
}

func (this *Configuration) Name() string {
	return "data"
}

func (this *Configuration) Init() error {
	workDir, workingDirError := os.Getwd()
	if workingDirError != nil {
		return workingDirError
	}
	this.RootPath = filepath.Join(workDir, this.RootPath)
	var err error
	this.watcher, err = fsnotify.NewWatcher()
	if err != nil {
		logger.Logger.Warn(" fsnotify.NewWatcher err:", err)
	}

	// 监听文件变化
	// Process events
	go func() {
		defer func() {
			if err := recover(); err != nil {
				logger.Logger.Warn("watch data director modify goroutine err:", err)
			}
		}()
		for {
			select {
			case ev, ok := <-this.watcher.Event:
				if ok && ev != nil {
					if ev.IsModify() || ev.IsRename() {
						obj := core.CoreObject()
						if filepath.Ext(ev.Name) == ".dat" {
							if obj != nil {
								obj.SendCommand(&DatFileModifiedCommand{fileName: ev.Name}, false)
							}
							logger.Logger.Info("fsnotify event:", ev)
						} else if filepath.Ext(ev.Name) == ".json" {
							if obj != nil {
								obj.SendCommand(&JsonFileModifiedCommand{fileName: ev.Name}, false)
							}
							logger.Logger.Info("fsnotify event:", ev)
						}
					}
				} else {
					return
				}
			case err := <-this.watcher.Error:
				logger.Logger.Warn("fsnotify err:", err)
			}
		}
		logger.Logger.Warnf("watcher quit! %v", this.RootPath)
	}()

	// 收集 DataLoader 处理的文件
	loaderFiles := []string{} // 文件地址，dat文件
	this.watcher.Watch(this.RootPath)
	filepath.Walk(this.RootPath, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			this.watcher.Watch(path) // 监听文件夹下的文件修改
		}
		name := info.Name()
		if filepath.Ext(name) != ".dat" {
			return nil
		}

		loaderFiles = append(loaderFiles, name)
		return nil
	})

	// 使用 DataLoader 加载
	for _, fileName := range loaderFiles {
		if IsLibFile(fileName) && this.LoadLib == false { //是牌库文件，但是不安排装载的话，就不加载库文件了
			continue
		}

		// loader
		loader := DataMgr.GetLoader(fileName)
		if loader != nil {
			fullPath := filepath.Join(this.RootPath, fileName)
			err := loader.Load(fullPath)
			if err != nil {
				logger.Logger.Warnf("%v loader err: %v", fileName, err)
			} else {
				logger.Logger.Infof("%v loader success", fileName)
			}
		} else {
			logger.Logger.Warnf("%v no loader", fileName)
		}

		// loaderAfter 依赖xlsx数据
		loaderAfter := DataMgrAfter.GetLoader(fileName)
		if loaderAfter != nil {
			fullPath := filepath.Join(this.RootPath, fileName)
			for _, v := range loaderAfter {
				err := v.Load(fullPath)
				if err != nil {
					logger.Logger.Warnf("%v loaderAfter err: %v", fileName, err)
				} else {
					logger.Logger.Infof("%v loaderAfter success", fileName)
				}
			}
		}
	}

	//todo 实现DataLoader
	err = updateClientVers()
	if err != nil {
		return err
	}
	//DB_Createroom
	CreateRoomMgrSington.Init()
	GameDropMgrSington.Init()
	//role pet
	RolePetMgrSington.Init()
	return nil
}

func (this *Configuration) Close() error {
	this.watcher.Close()
	return nil
}

func init() {
	core.RegistePackage(&Config)
}
