package game

import (
	"fmt"
	"server/GoUtil"
	"server/db"
	"server/game/mod/msg"
	"sort"
	"strconv"
)

const (
	RANK_TIME_SORT = 3000000000
)

type RankMgr struct {
	*ServerMod
}

type RankData struct {
	List      map[int][]*Rank // 玩家排行榜
	Champship map[int][]*Rank // 锦标赛排行榜
	BackData  map[int][]*Rank // 玩家排行榜 备份
}

type RankInfo struct {
	List    []*Rank
	MyRank  int
	MyScore float64
}

const (
	RANK_TYPE_USER   = 1 // 玩家排行榜
	RANK_TYPE_GLOBAL = 2 // 全球排行榜

	RANK_USER = "rank_user" // redis玩家排行榜
)

type Rank struct {
	Uid   int
	Score float64
	Time  int64
}

type RankMsg struct {
	Uid      int
	Score    float64
	RankType int
}

func (r *RankMgr) Init() {
	r.key = RANK_MGR_KEY
	r.data = &RankData{
		List: make(map[int][]*Rank, 0),
	}
	// 注册处理函数
	r.init()
	r.RegisterHandler(msg.HANDLE_TYPE_RANK, r.inRank)
	r.RegisterHandler(msg.HANDLE_TYPE_RANK_INFO, r.getRankInfo)
	r.RegisterHandler(msg.SERVER_ZERO_UPDATE, r.ZeroUpdate)
}

func (r *RankMgr) getData() *RankData {
	return r.data.(*RankData)
}

// 零点更新 重置榜单
func (r *RankMgr) ZeroUpdate(m *msg.Msg) (interface{}, error) {
	return nil, nil
}

// 获取榜单数据
func (r *RankMgr) getRank(RankType int) []*Rank {
	if v, ok := r.getData().List[RankType]; ok {
		len := min(100, len(v))
		return v[:len]
	}
	return []*Rank{}
}

func (r *RankMgr) getAllRank(RankType int) []*Rank {
	if v, ok := r.getData().List[RankType]; ok {
		return v
	}
	return []*Rank{}
}

func (r *RankMgr) getMyRank(Uid, RankType int) (int, float64) {
	if d, ok := r.getData().List[RankType]; ok {
		for k, v := range d {
			if v.Uid == Uid {
				return k + 1, v.Score
			}
		}
	}
	return 0, 0.0
}

// 设置榜单数据
func (r *RankMgr) setRank(RankType int, data []*Rank) {
	r.getData().List[RankType] = data
}

// 获取排行榜信息
func (r *RankMgr) getRankInfo(m *msg.Msg) (interface{}, error) {
	data := m.Extra.(RankMsg)
	if data.RankType == RANK_TYPE_GLOBAL {
		return r.getRedisRankInfo(m)
	}
	rankList := r.getRank(data.RankType)
	MyRank, MyScore := r.getMyRank(m.From, data.RankType)
	return &RankInfo{
		List:    rankList,
		MyRank:  MyRank,
		MyScore: MyScore,
	}, nil
}

func (r *RankMgr) getRedisRankInfo(m *msg.Msg) (interface{}, error) {
	RedisList, err := db.RedisZRevRangeWithScores(RANK_USER, 0, 100)
	if err != nil {
		return &RankInfo{}, nil
	}
	sort.Slice(RedisList, func(i, j int) bool { // 排序 从大到小
		return RedisList[i].Score > RedisList[j].Score
	})
	rankList := make([]*Rank, 0)
	for _, v := range RedisList {
		rankList = append(rankList, &Rank{
			Uid:   GoUtil.Int(v.Member),
			Score: v.Score,
			Time:  GoUtil.Now(),
		})
	}
	MyRank, MyScore, _ := db.RedisZRankWithScores(RANK_USER, strconv.Itoa(m.From))
	return &RankInfo{
		List:    rankList,
		MyRank:  int(MyRank),
		MyScore: MyScore,
	}, nil
}

// 进入排行榜
func (r *RankMgr) inRank(m *msg.Msg) (interface{}, error) {
	data := m.Extra.(RankMsg)
	rankList := r.getRank(data.RankType)
	inRank := false
	for _, v := range rankList {
		if v.Uid == data.Uid {
			if v.Score < data.Score {
				v.Score = data.Score
				v.Time = m.SendT
				inRank = true
				break
			}
			return nil, nil
		}
	}

	if !inRank {
		rankList = append(rankList, &Rank{Uid: data.Uid, Score: data.Score, Time: m.SendT})
	}
	sort.Slice(rankList, func(i, j int) bool { // 排序 从大到小 数值相等按时间排序
		if rankList[i].Score > rankList[j].Score {
			return true
		} else if rankList[i].Score == rankList[j].Score {
			return rankList[i].Time < rankList[j].Time
		}
		return false
	})

	// if len(rankList) >= 100 {
	// 	rankList = rankList[:100]
	// }
	r.setRank(data.RankType, rankList)
	if data.RankType == RANK_TYPE_USER {
		Uid := strconv.Itoa(data.Uid)
		TimeSort := fmt.Sprintf("0.%d", RANK_TIME_SORT-GoUtil.Now())
		TimeSortF, _ := strconv.ParseFloat(TimeSort, 64)
		db.RedisZAdd(RANK_USER, Uid, data.Score+TimeSortF)
	}
	r.update = true
	return nil, nil
}

func (r *RankMgr) ClearRank(RankType int) {
	// if RankType == RANK_TYPE_GLOBAL {
	// 	db.RedisDel(RANK_USER)
	// 	return
	// }
	r.setRank(RankType, []*Rank{})
}
