package mergeCluster

import (
	"fmt"
	"math"
	"server/conf"
	"server/game/mod/msg"
	GoUtil "server/game_util"
	"server/pkg/github.com/name5566/leaf/log"
	"server/pkg/github.com/name5566/leaf/network"
	"sync"
)

const (
	ClusterCenterId = 0 // 集群中心
)

var FuncMap = map[int]func(*Agent, *msg.Msg) error{} // 消息处理函数
var funcMapMu sync.RWMutex                           // FuncMap 的读写锁
var CallbackChan = make(map[string]chan *msg.Msg)    // 回调消息队列
var callbackChanMu sync.RWMutex                      // CallbackChan 的读写锁
var (
	server      *network.TCPServer          // 服务器
	Center      *network.TCPClient          // 集群中心
	clients     []*network.TCPClient        // 集群客户端
	MsgChan     = make(chan *msg.Msg, 1000) // 消息队列
	serverAgent sync.Map                    // 服务器Agent
)

func Init() {
	if conf.Server.ListenAddr != "" {
		server = new(network.TCPServer)
		server.Addr = conf.Server.ListenAddr
		server.MaxConnNum = int(math.MaxInt32)
		server.PendingWriteNum = 1 << 14
		server.LenMsgLen = 4
		server.MaxMsgLen = 1 << 16
		server.NewAgent = newServerAgent
		server.Start()
	}

	if conf.Server.CenterAddr != "" && conf.Server.ServerType != "center" {
		connectRemote(conf.Server.CenterAddr, ClusterCenterId, "center")
	}

	registerFunc(msg.CLUSTER_HANDSHAKE_1, HandShakeRecv)
	registerFunc(msg.CLUSTER_HANDSHAKE_2, HandShakeRecv2)
	registerFunc(msg.CLUSTER_JOIN, ClusterJoin)
	registerFunc(msg.CLUSTER_EXIT, ClusterExit)
}

// GetCallbackChanMu 返回 CallbackChan 的读写锁，供外部包安全访问 CallbackChan
func GetCallbackChanMu() *sync.RWMutex {
	return &callbackChanMu
}

func Destroy() {
	if server != nil {
		log.Release("closing cluster server")
		server.Close()
	}

	for _, client := range clients {
		client.Close()
	}
}

type Agent struct {
	conn     *network.TCPConn
	ServerId int
	Type     int
}

func newAgent(conn *network.TCPConn) network.Agent {
	a := new(Agent)
	a.conn = conn
	return a
}

func newServerAgent(conn *network.TCPConn) network.Agent {
	a := new(Agent)
	a.conn = conn
	a.Type = 1
	return a
}

func (a *Agent) Run() {
	HandShake(a)
	for {
		data, err := a.conn.ReadMsg()
		if err != nil {
			log.Debug("read message error: %v", err)
			break
		}
		m := msg.Msg{}
		err = GoUtil.GobUnmarshal(data, &m)
		if err != nil {
			log.Debug("decode err: %v", err)
			return
		}
		err = processMsg(a, &m)
		if err != nil {
			log.Debug("ProcessMsg err: %v", err)
		}
	}
}

func (a *Agent) WriteMsg(data interface{}) {
	err := a.conn.WriteMsg(data.([]byte))
	if err != nil {
		fmt.Println(err)
	}
}

func (a *Agent) OnClose() {
	log.Debug("server %d close", a.ServerId)
	serverAgent.Delete(a.ServerId)
}
