package main

import (
	"mongo.games.com/goserver/core/logger"
	"mongo.games.com/goserver/core/netlib"
	"mongo.games.com/goserver/mmo/protocol"
	"mongo.games.com/goserver/srvlib"
)

var (
	SessionHandlerClientBalanceName = "handler-client-balance"
	SessionHandlerClientBalanceMgr  = &SessionHandlerClientBalance{gates: make(map[int32]*gateService)}
)

type gateService struct {
	load   int
	active bool
}

type SessionHandlerClientBalance struct {
	netlib.BasicSessionHandler
	gates map[int32]*gateService
}

func (sfcb SessionHandlerClientBalance) GetName() string {
	return SessionHandlerClientBalanceName
}

func (sfcb *SessionHandlerClientBalance) GetInterestOps() uint {
	return 1 << netlib.InterestOps_Opened
}

func (sfcb *SessionHandlerClientBalance) OnSessionOpened(s *netlib.Session) {
	logger.Logger.Trace("SessionHandlerClientBalance.OnSessionOpened")
	services := srvlib.ServiceMgr.GetServices(srvlib.ClientServiceType)
	if services != nil {
		/*清理掉线的gate*/
		for k, _ := range sfcb.gates {
			if _, has := services[k]; !has {
				logger.Logger.Trace("gate leave: ", k)
				delete(sfcb.gates, k)
			}
		}
		/*补充新上线的gate*/
		for k, v := range services {
			if _, has := sfcb.gates[k]; !has {
				sfcb.gates[k] = &gateService{active: true}
				logger.Logger.Trace("new gate come in: ", k, v)
			}
		}
	}

	/*查找最小负载的gate*/
	var minsrvid int32
	var min = 100000
	for k, v := range sfcb.gates {
		if v.active && v.load < min {
			minsrvid = k
			min = v.load
		}
	}

	pack := &protocol.SCGateInfo{}
	if mls, has := services[minsrvid]; has {
		pack.SrvType = mls.GetSrvType()
		pack.SrvId = mls.GetSrvId()
		pack.AuthKey = mls.GetAuthKey()
		pack.Ip = mls.GetOuterIp()
		pack.Port = mls.GetPort()
	}
	s.Send(int(protocol.MmoPacketID_PACKET_SC_GATEINFO), pack)
	logger.Logger.Trace(pack)
	s.Close()
}

func init() {
	netlib.RegisteSessionHandlerCreator(SessionHandlerClientBalanceName, func() netlib.SessionHandler {
		return SessionHandlerClientBalanceMgr
	})

	netlib.RegisterFactory(int(protocol.MmoPacketID_PACKET_GB_CUR_LOAD), netlib.PacketFactoryWrapper(func() interface{} {
		return &protocol.ServerLoad{}
	}))

	netlib.RegisterHandler(int(protocol.MmoPacketID_PACKET_GB_CUR_LOAD), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		if sr, ok := pack.(*protocol.ServerLoad); ok {
			srvid := sr.GetSrvId()
			if v, has := SessionHandlerClientBalanceMgr.gates[srvid]; has {
				v.load = int(sr.GetCurLoad())
				logger.Logger.Trace("receive gate load info 1, sid=", srvid, " load=", v.load)
			} else {
				services := srvlib.ServiceMgr.GetServices(srvlib.ClientServiceType)
				if _, has := services[srvid]; has {
					SessionHandlerClientBalanceMgr.gates[srvid] = &gateService{active: true, load: int(sr.GetCurLoad())}
					logger.Logger.Trace("receive gate load info 2, sid=", srvid, " load=", sr.GetCurLoad())
				}
			}
		}
		return nil
	}))
}
