package managecenterMgr

import (
	"encoding/json"
	"errors"
	"fmt"
	"sort"

	"Framework/ipMgr"
	"Framework/managecenterModel"
	. "Framework/managecenterModel"
	"goutil/logUtil"
	"goutil/webUtil"
)

var (
	// 服务器组集合
	serverGroupMap  = make(map[int32]*ServerGroup, 512)
	serverGroupHash string

	// 服务器组变化方法集合 (完整列表，新增列表，删除列表，更新列表)
	serverGroupChangeFuncMap = make(map[string]func([]*ServerGroup, []*ServerGroup, []*ServerGroup, []*ServerGroup))
)

func init() {
	ipMgr.RegisterIpCheckFunc("ServerGroupIpCheck", isIpValid)
}

// 重新加载服务器组
func reloadServerGroup(isInit bool) error {
	//logUtil.DebugLog("开始刷新服务器组信息")

	url := getManageCenterUrl("/API/ServerGroupList.ashx")

	// 定义请求参数
	postDict := make(map[string]string)
	postDict["GroupType"] = "Mix"
	postDict["HashValue"] = serverGroupHash

	//请求url,请求头
	header := webUtil.GetFormHeader()
	transport := webUtil.NewTransport()
	transport.DisableKeepAlives = true
	transport = webUtil.GetTimeoutTransport(transport, 30)

	statusCode, returnBytes, err := webUtil.PostMapData(url, postDict, header, transport)
	//statusCode, returnBytes, err := webUtil.PostMapData(url, postDict, header, nil)
	if err != nil {
		logUtil.ErrorLog(fmt.Sprintf("获取服务器组列表出错，url:%s,错误信息为:%s", url, err))
		return err
	}
	if statusCode != 200 {
		logUtil.ErrorLog(fmt.Sprintf("获取服务器组列表出错，url:%s,错误码为:%d", url, statusCode))
		return err
	}

	// 解析返回值
	returnObj := new(ReturnObject)
	if err = json.Unmarshal(returnBytes, &returnObj); err != nil {
		logUtil.ErrorLog(fmt.Sprintf("获取服务器组列表出错，反序列化返回值出错，错误信息为：%s", err))
		return err
	}

	// 判断返回状态是否为成功
	if returnObj.Code != 0 {
		// 数据没有变化，所以没有获取到新的数据，不能算错误。
		if returnObj.Code == 47 || returnObj.Message == "DataNotChanged" {
			//如果本地集合为空，且数据又没变化时，重新初始化一下本地hash值
			if len(serverGroupMap) == 0 {
				serverGroupHash = ""
			}
			return nil
		} else {
			msg := fmt.Sprintf("获取服务器组列表出错，返回状态：%d，信息为：%s", returnObj.Code, returnObj.Message)
			logUtil.ErrorLog(msg)
			return errors.New(msg)
		}
	}

	// 解析Data
	tmpServerGroupList := make([]*ServerGroup, 0, 512)
	if data, ok := returnObj.Data.(string); !ok {
		msg := "获取服务器组列表出错，返回的数据不是string类型"
		logUtil.ErrorLog(msg)
		return errors.New(msg)
	} else {
		if err = json.Unmarshal([]byte(data), &tmpServerGroupList); err != nil {
			logUtil.ErrorLog(fmt.Sprintf("获取服务器组列表出错，反序列化数据出错，错误信息为：%s", err))
			return err
		}
	}

	//logUtil.DebugLog(fmt.Sprintf("刷新服务器组信息结束,服务器组数量:%d", len(tmpServerGroupList)))

	tmpServerGroupMap := make(map[int32]*ServerGroup, 512)
	for _, item := range tmpServerGroupList {
		tmpServerGroupMap[item.Id] = item
	}

	// 处理服务器组是否变化情况
	addList, deleteList, updateList := handleServerGroupChange(GetServerGroupMap(), tmpServerGroupMap)
	triggerServerGroupChangeFunc(tmpServerGroupList, addList, deleteList, updateList)

	// 赋值给最终的ServerGroupMap
	serverGroupMap = tmpServerGroupMap
	serverGroupHash = returnObj.HashValue

	//通知变更
	mcDataChangeCallBack(managecenterModel.ServerGroupData, isInit)

	return nil
}

// 处理服务器组是否变化情况
// originalServerGroupMap: 当前服务器组集合
// newServerGroupMap: 新的服务器组集合
func handleServerGroupChange(currServerGroupMap, newServerGroupMap map[int32]*ServerGroup) (
	addList []*ServerGroup, deleteList []*ServerGroup, updateList []*ServerGroup) {

	// 判断是否有新增的数据
	for k, v := range newServerGroupMap {
		if _, exist := currServerGroupMap[k]; !exist {
			addList = append(addList, v)
		}
	}

	// 判断是否有删除的数据
	for k, v := range currServerGroupMap {
		if _, exist := newServerGroupMap[k]; !exist {
			deleteList = append(deleteList, v)
		}
	}

	// 判断是否有更新的数据
	for k, currItem := range currServerGroupMap {
		if newItem, exist := newServerGroupMap[k]; exist {
			if currItem.IsEqual(newItem) == false {
				updateList = append(updateList, newItem)
			}
		}
	}

	return
}

// 触发服务器组变化的方法
func triggerServerGroupChangeFunc(allList []*ServerGroup, addList []*ServerGroup, deleteList []*ServerGroup, updateList []*ServerGroup) {
	// 如果有注册服务器组变化的方法
	if len(serverGroupChangeFuncMap) > 0 {
		for _, serverGroupChangeFunc := range serverGroupChangeFuncMap {
			serverGroupChangeFunc(allList, addList, deleteList, updateList)
		}
	}
}

// 注册服务器组变化方法
// funcName：方法名称
// serverGroupChangeFunc：服务器组变化方法
func RegisterServerGroupChangeFunc(funcName string, serverGroupChangeFunc func([]*ServerGroup, []*ServerGroup, []*ServerGroup, []*ServerGroup)) {
	if _, exists := serverGroupChangeFuncMap[funcName]; exists {
		panic(fmt.Errorf("RegisterServerGroupChange:%s已经存在，请检查", funcName))
	}
	serverGroupChangeFuncMap[funcName] = serverGroupChangeFunc

	logUtil.DebugLog(fmt.Sprintf("注册服务器组变化方法 funcName:%s，当前共有%d个注册", funcName, len(serverGroupChangeFuncMap)))
}

// 获取服务器组集合
// 返回值：
// 服务器组集合
func GetServerGroupMap() (retServerGroupMap map[int32]*ServerGroup) {
	retServerGroupMap = make(map[int32]*ServerGroup, 128)
	for k, v := range serverGroupMap {
		retServerGroupMap[k] = v
	}

	return
}

// 获取服务器组列表
// 返回值：
// 服务器组列表
func GetServerGroupList() (serverGroupList []*ServerGroup) {
	for _, item := range serverGroupMap {
		serverGroupList = append(serverGroupList, item)
	}

	sort.Slice(serverGroupList, func(i, j int) bool {
		return serverGroupList[i].SortByIdAsc(serverGroupList[j])
	})

	return
}

// 获取服务器组项
// id
// 返回值：
// 服务器组对象
// 是否存在
func GetServerGroupItem(id int32) (serverGroupObj *ServerGroup, exist bool) {
	serverGroupObj, exist = serverGroupMap[id]
	return
}

// 根据合作商Id、服务器Id获取服务器组对象
// partnerId：合作商Id
// serverId：服务器Id
// 返回值：
// 服务器组对象
// 服务器对象
// 是否存在
func GetServerGroup(partnerId, serverId int32) (serverGroupObj *ServerGroup, serverObj *Server, exist bool) {
	var partnerObj *Partner

	// 获取合作商对象
	partnerObj, exist = GetPartner(partnerId)
	if !exist {
		return
	}

	// 获取服务器对象
	serverObj, exist = GetServer(partnerObj, serverId)
	if !exist {
		return
	}

	// 获取服务器组对象
	serverGroupObj, exist = GetServerGroupItem(serverObj.GroupId)
	return
}

// 判断IP是否有效
// ip：指定IP地址
// 返回值：
// IP是否有效
func isIpValid(ip string) (exist bool) {
	for _, v := range serverGroupMap {
		for _, item := range v.GetIPList() {
			if ip == item {
				exist = true
				return
			}
		}
	}

	return
}
