package clientMgr

import (
	"encoding/json"
	"sync"

	"goutil/debugUtil"

	"goutil/logUtil"
)

var (
	clientMap = make(map[int32]IClient, 1024)
	mutex     sync.RWMutex
)

func RegisterClient(clientObj IClient) {
	mutex.Lock()
	defer mutex.Unlock()

	clientMap[clientObj.GetId()] = clientObj
}

func UnregisterClient(clientObj IClient) {
	mutex.Lock()
	defer mutex.Unlock()

	delete(clientMap, clientObj.GetId())
}

func GetClient(id int32) (clientObj IClient, exists bool) {
	mutex.RLock()
	defer mutex.RUnlock()

	clientObj, exists = clientMap[id]
	return
}

func getClientCount() int {
	mutex.RLock()
	defer mutex.RUnlock()

	return len(clientMap)
}

func getExpiredClientList() (expiredList []IClient) {
	mutex.RLock()
	defer mutex.RUnlock()

	for _, item := range clientMap {
		if item.Expired() {
			expiredList = append(expiredList, item)
		}
	}

	return
}

// 绑定连接到玩家
func BindClientAndPlayer(clientObj IClient, playerObj *Player) {
	// 发送在另一台设备登陆的信息
	sendLoginAnotherDeviceMsg := func(clientObj IClient) {
		responseObj := NewServerResponseObject()
		responseObj.SetMethodName("Login")
		responseObj.SetResultStatus(LoginOnAnotherDevice)

		mes, _ := json.Marshal(responseObj)

		if debugUtil.IsDebug() {
			logUtil.WarnLog("BindClientAndPlayer11BindClientAndPlayer:%v", string(mes))
		}

		// 先发送消息，然后再断开连接
		clientObj.SendMessage(responseObj)
		clientObj.SendMessage(NewDisconnectServerResponseObject())
	}

	// 立即更新活跃时间，避免在将要清除时，玩家又登陆的极端情况
	clientObj.Active()
	clientObj.ClearSendData()

	// 判断是否重复登陆
	if playerObj.ClientId > 0 {
		if oldClientObj, exist := GetClient(playerObj.ClientId); exist {
			// 如果不是同一个客户端，则先给客户端发送在其他设备登陆信息，然后断开连接
			if clientObj != oldClientObj {
				sendLoginAnotherDeviceMsg(oldClientObj)
			}
		}
	}

	// 更新客户端对象的玩家Id、以及玩家对象对应的客户端Id
	clientObj.PlayerLogin(playerObj.Id)
	playerObj.ClientLogin(clientObj.GetId())
}

// Disconnect 清理断开的连接数据
// / 连接对象
func Disconnect(clientObj IClient) {
	if clientObj.GetPlayerId() != 0 {
		playerObj, exist, err := getPlayerHandler(clientObj.GetPlayerId(), false)
		if err == nil && exist && clientObj.GetId() == playerObj.ClientId {
			playerObj.ClientLogout()
		}
	}

	clientObj.Close()
	UnregisterClient(clientObj)
}
