package srvlib

import (
	"strings"

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

/*
 服务器信息注册，单个服务器可能包含多个子服务端口
*/

var (
	SessionAttributeServerInfo = &ServerSessionMgr{}
	ServerSessionMgrSington    = &ServerSessionMgr{sessions: make(map[int]map[int]map[int]*netlib.Session)}
)

type ServerSessionRegisteListener interface {
	OnRegiste(*netlib.Session)
	OnUnregiste(*netlib.Session)
}

type ServerSessionMgr struct {
	sessions  map[int]map[int]map[int]*netlib.Session //keys=>areaid:type:id
	listeners []ServerSessionRegisteListener
}

// AddListener 添加一个服务器会话注册监听器
func (ssm *ServerSessionMgr) AddListener(l ServerSessionRegisteListener) ServerSessionRegisteListener {
	ssm.listeners = append(ssm.listeners, l)
	return l
}

// RegisteSession 注册一个新的服务器会话
func (ssm *ServerSessionMgr) RegisteSession(s *netlib.Session) bool {
	attr := s.GetAttribute(SessionAttributeServerInfo)
	if attr == nil {
		logger.Logger.Warnf("服务器注册信息为空")
		return false
	}

	srvInfo, ok := attr.(*protocol.SSSrvRegiste)
	if !ok || srvInfo == nil {
		logger.Logger.Warnf("服务器注册信息错误")
		return false
	}

	areaId := int(srvInfo.GetAreaId())
	srvType := int(srvInfo.GetType())
	srvId := int(srvInfo.GetId())

	if _, ok := ssm.sessions[areaId]; !ok {
		ssm.sessions[areaId] = make(map[int]map[int]*netlib.Session)
	}
	if _, ok := ssm.sessions[areaId][srvType]; !ok {
		ssm.sessions[areaId][srvType] = make(map[int]*netlib.Session)
	}

	session, has := ssm.sessions[areaId][srvType][srvId]
	if has && session != nil && session != s {
		logger.Logger.Infof("删除旧服务器注册: %v", srvInfo)
		ssm.UnregisteSession(session)
	}

	logger.Logger.Infof("服务器注册成功：%v", srvInfo)
	ssm.sessions[areaId][srvType][srvId] = s
	if len(ssm.listeners) != 0 {
		for _, l := range ssm.listeners {
			l.OnRegiste(s)
		}
	}

	return true
}

// UnregisteSession 注销一个服务器会话
func (ssm *ServerSessionMgr) UnregisteSession(s *netlib.Session) bool {
	attr := s.GetAttribute(SessionAttributeServerInfo)
	if attr == nil {
		return false
	}

	srvInfo, ok := attr.(*protocol.SSSrvRegiste)
	if !ok || srvInfo == nil {
		return false
	}

	logger.Logger.Infof("尝试删除服务器注册：%v", srvInfo)
	areaId := int(srvInfo.GetAreaId())
	srvType := int(srvInfo.GetType())
	srvId := int(srvInfo.GetId())

	if a, exist := ssm.sessions[areaId]; exist {
		if b, exist := a[srvType]; exist {
			if conn, exist := b[srvId]; exist && s == conn {
				logger.Logger.Infof("删除服务器注册成功 %v", srvInfo)
				delete(b, srvId)
				if len(ssm.listeners) != 0 {
					for _, l := range ssm.listeners {
						l.OnUnregiste(s)
					}
				}
				return true
			} else {
				logger.Logger.Infof("服务器注册信息已经删除")
				return false
			}
		}
	}

	logger.Logger.Infof("服务器注册信息没找到：%v", srvInfo)

	return false
}

// GetSession 根据区域ID、服务器类型和服务器ID获取会话
func (ssm *ServerSessionMgr) GetSession(areaId, srvType, srvId int) *netlib.Session {
	if a, exist := ssm.sessions[areaId]; exist {
		if b, exist := a[srvType]; exist {
			if c, exist := b[srvId]; exist {
				return c
			}
		}
	}
	return nil
}

// GetSessions 获取指定区域和服务器类型的所有会话
func (ssm *ServerSessionMgr) GetSessions(areaId, srvType int) (sessions []*netlib.Session) {
	if a, exist := ssm.sessions[areaId]; exist {
		if b, exist := a[srvType]; exist {
			for _, s := range b {
				sessions = append(sessions, s)
			}
		}
	}
	return
}

// GetServerId 获取指定区域和服务器类型的第一个服务器ID
func (ssm *ServerSessionMgr) GetServerId(areaId, srvType int) int {
	if a, exist := ssm.sessions[areaId]; exist {
		if b, exist := a[srvType]; exist {
			for sid := range b {
				return sid
			}
		}
	}
	return -1
}

// GetServerIdByMaxData 根据最大数据获取指定区域和服务器类型的服务器ID
func (ssm *ServerSessionMgr) GetServerIdByMaxData(areaId, srvType int) int {
	var bestSid int = -1
	var data string
	if a, exist := ssm.sessions[areaId]; exist {
		if b, exist := a[srvType]; exist {
			for sid, s := range b {
				if srvInfo, ok := s.GetAttribute(SessionAttributeServerInfo).(*protocol.SSSrvRegiste); ok && srvInfo != nil {
					if strings.Compare(data, srvInfo.GetData()) <= 0 {
						data = srvInfo.GetData()
						bestSid = sid
					}
				}
			}
		}
	}
	return bestSid
}

// GetServerIds 获取指定区域和服务器类型的所有服务器ID
// 参数:
//   - areaId: 区域ID
//   - srvType: 服务器类型
//
// 返回:
//   - ids: 包含所有匹配服务器ID的切片
func (ssm *ServerSessionMgr) GetServerIds(areaId, srvType int) (ids []int) {
	// 检查指定区域是否存在
	if a, exist := ssm.sessions[areaId]; exist {
		// 检查指定服务器类型是否存在
		if b, exist := a[srvType]; exist {
			// 遍历所有匹配的服务器，收集它们的ID
			for sid := range b {
				ids = append(ids, sid)
			}
		}
	}
	return
}

// Broadcast 向指定区域和服务器类型广播消息
func (ssm *ServerSessionMgr) Broadcast(packetid int, pack interface{}, areaId, srvType int) {
	if areaId >= 0 {
		if srvType >= 0 {
			// 向特定区域和服务器类型广播
			if a, exist := ssm.sessions[areaId]; exist {
				if b, exist := a[srvType]; exist {
					for _, s := range b {
						s.Send(packetid, pack)
					}
				}
			}
		} else {
			// 向特定区域的所有服务器类型广播
			if a, exist := ssm.sessions[areaId]; exist {
				for _, b := range a {
					for _, s := range b {
						s.Send(packetid, pack)
					}
				}
			}
		}
	} else {
		if srvType >= 0 {
			// 向所有区域的特定服务器类型广播
			for _, a := range ssm.sessions {
				if b, exist := a[srvType]; exist {
					for _, s := range b {
						s.Send(packetid, pack)
					}
				}
			}
		} else {
			// 向所有区域的所有服务器类型广播
			for _, a := range ssm.sessions {
				for _, b := range a {
					for _, s := range b {
						s.Send(packetid, pack)
					}
				}
			}
		}
	}
}
