package servers

import (
	"leafstalk/conf"
	msg "leafstalk/covenant/pbfmsg"
	"sync"
	"time"

	"leafstalk/log"
	"leafstalk/network/cluster"
)

type OfflineServer struct {
	Id   int64
	Tick int64
}

var DisconnectMutex sync.Mutex
var DisconnectServers map[int64]*OfflineServer

// rpcNewClusterAgent 有新的服务器链接，添加服务器
func OnRpcNewClusterAgent(args []interface{}, conf *conf.Config) {

	a := args[0].(*cluster.ServerAgent)
	isListenServer := args[1].(bool)
	log.Infof("rpcNewClusterAgent %v", a.RemoteAddr())

	//加入认证列表，等待认证
	server := NewServer(a)
	a.SetUserData(server)
	AddWaitAuthServer(server, isListenServer)
	if isListenServer {
		IntroduceServerSelf(server, conf)
	}

	//认证过程可能比较慢，需要等待对方响应
	//主动连接方需要主动发认证消息
	//连接断开时，就不需要认证了
}

// rpcCloseClusterAgent 服务器断开链接
func OnRpcCloseClusterAgent(args []interface{}) {

	a := args[0].(*cluster.ServerAgent)
	log.Infof("rpcCloseClusterAgent %v", a.RemoteAddr())

	if server := ResolveServerAgent(a); server != nil {
		if server.ID > 0 {
			AddDisconnectServer(server.ID)
		}
		RemoveServer(server)
		RemoveAuthServer(server)

	} else {
		log.Errorf("RemoveServer but userData is nil")
	}

	//与服务器断开连接，
	//如果对方是游戏服务器的话，是否删除所有在线玩家，需要看是否无状态
}

// IntroduceServerSelf 服务器之间进行认证
func IntroduceServerSelf(server *Server, conf *conf.Config) {

	log.Infof("IntroduceServerSelf %v", server)
	//发送登录消息
	id := conf.GetInt64("cluster.id")
	serverType := conf.GetString("cluster.servertype")
	lines := conf.GetIntSlice("cluster.lines")
	addr := conf.GetString("gate.toclient.wsaddr")
	msg1 := msg.ServerLogin{
		ID:       id,
		Type:     serverType,
		GateAddr: addr,
	}
	for _, v := range lines {
		msg1.Lines = append(msg1.Lines, int32(v))
	}
	server.Agent.WriteMsg(&msg1)
}

func AuthAllServer(conf *conf.Config) {
	RangeListenServer(func(server *Server) {
		IntroduceServerSelf(server, conf)
	})
}

func HandleServerLogin(args []interface{}, conf *conf.Config) {

	a := args[1].(*cluster.ServerAgent)
	request := args[0].(*msg.ServerLogin)

	if request.ID == 0 {
		log.Warnf("handleServerLogin faild, id can not be 0, %v %v", request.Type, request.GateAddr)
		return
	}
	log.Infof("handleServerLogin, id=%v, type=%v", request.ID, request.Type)

	if server := ResolveServerAgent(a); server != nil {
		server.ID = request.ID
		server.Type = request.Type
		server.Addr = request.GateAddr
		for _, v := range request.Lines {
			server.Lines = append(server.Lines, int(v))
		}

		RemoveDisconnectServer(server.ID)
		RemoveAuthServer(server)
		AddServer(server)

		//回应
		id := conf.GetInt64("cluster.id")
		serverType := conf.GetString("cluster.servertype")
		lines := conf.GetIntSlice("cluster.lines")
		addr := conf.GetString("gate.toclient.wsaddr")
		msg1 := msg.ResponseServerLogin{
			ID:       id,
			Type:     serverType,
			GateAddr: addr,
			// Lines:    int32(group),
		}
		for _, v := range lines {
			msg1.Lines = append(msg1.Lines, int32(v))
		}
		a.WriteMsg(&msg1)
	}
}

func HandleResponseServerLogin(args []interface{}) {

	a := args[1].(*cluster.ServerAgent)
	request := args[0].(*msg.ResponseServerLogin)

	if request.ID == 0 {
		log.Warnf("handleResponseServerLogin faild, id can not be 0, %v %v", request.Type, request.GateAddr)
		return
	}
	log.Infof("handleResponseServerLogin, id=%v, type=%v", request.ID, request.Type)
	if a.UserData() != nil {
		if server, ok := a.UserData().(*Server); ok {
			server.ID = request.ID
			server.Type = request.Type
			server.Addr = request.GateAddr
			// server.Group = int(request.Group)

			for _, v := range request.Lines {
				server.Lines = append(server.Lines, int(v))
			}

			RemoveDisconnectServer(server.ID)
			RemoveAuthServer(server)
			AddServer(server)
		}
	}
}

func ResolveServerAgent(agent *cluster.ServerAgent) *Server {
	if agent == nil {
		return nil
	}

	userData := agent.UserData()
	if userData == nil {
		return nil
	}

	switch v := userData.(type) {
	case int64:
		return nil
	case *Server:
		return v
	}

	return nil
}

// 添加离线服务器
func AddDisconnectServer(id int64) {
	if id <= 0 {
		return
	}
	DisconnectMutex.Lock()
	defer DisconnectMutex.Unlock()
	if DisconnectServers == nil {
		DisconnectServers = make(map[int64]*OfflineServer)
	}
	for _, v := range DisconnectServers {
		if v.Id == id {
			return
		}
	}

	s := new(OfflineServer)
	s.Id = id
	s.Tick = time.Now().Unix()
	DisconnectServers[id] = s
}

func RemoveDisconnectServer(id int64) {
	DisconnectMutex.Lock()
	defer DisconnectMutex.Unlock()

	delete(DisconnectServers, id)
}

// 检查离线时长
func CheckOfflineTimeLong(id int64) int64 {
	DisconnectMutex.Lock()
	defer DisconnectMutex.Unlock()

	var tl int64 = -1
	for _, v := range DisconnectServers {
		if v.Id == id {
			c := time.Now().Unix()
			tl = c - v.Tick
			if tl < 0 {
				v.Tick = c
				tl = 0
			}
			break
		}
	}
	return tl
}

// 获取离线超时服务器 S
func GetOfflineServer(timeOut int64) []int64 {
	DisconnectMutex.Lock()
	defer DisconnectMutex.Unlock()

	var lst []int64
	c := time.Now().Unix()
	for _, v := range DisconnectServers {
		if c-v.Tick > timeOut {
			lst = append(lst, v.Id)
		}
	}
	return lst
}

// func IsDisconnectServer(id int) bool {
// 	for _, v := range DisconnectServers {
// 		if v.Id == id {
// 			return true
// 		}
// 	}
// 	return false
// }
