package main

import (
	"fmt"
	"sort"

	"mongo.games.com/goserver/core/logger"

	"mongo.games.com/game/common"
	"mongo.games.com/game/protocol/server"
	"mongo.games.com/game/srvdata"
)

type ChessMatchItem struct {
	Index   int
	Id      int32
	Score   int64
	SceneId int
}

type ChessMatchPool struct {
	List   []*ChessMatchItem
	IdItem map[int32]*ChessMatchItem
}

func (c *ChessMatchPool) Len() int {
	return len(c.List)
}

func (c *ChessMatchPool) Less(i, j int) bool {
	return c.List[i].Score < c.List[j].Score
}

func (c *ChessMatchPool) Swap(i, j int) {
	c.List[i].Index = j
	c.List[j].Index = i
	c.List[i], c.List[j] = c.List[j], c.List[i]
}

// Add .
// id snid
func (c *ChessMatchPool) Add(id int32, score int64, sceneId int) {
	if _, ok := c.IdItem[id]; ok {
		return
	}

	item := &ChessMatchItem{
		Index:   len(c.List),
		Id:      id,
		Score:   score,
		SceneId: sceneId,
	}
	c.List = append(c.List, item)
	c.IdItem[id] = item

	sort.Sort(c)
}

func (c *ChessMatchPool) Del(id int32) {
	item, ok := c.IdItem[id]
	if !ok {
		return
	}

	c.List = append(c.List[:item.Index], c.List[item.Index:]...)

	for i := item.Index; i < len(c.List); i++ {
		c.List[i].Index = i
	}
}

// ChessMatchFunc 国际象棋匹配规则
func ChessMatchFunc(csp *CoinScenePool, p *Player, scenes map[int]*Scene, sameIpLimit bool, exclude []int32) *Scene {
	if csp == nil || p == nil {
		return nil
	}

	var cmp *ChessMatchPool
	var ok bool
	if csp.extraData != nil {
		cmp, ok = csp.extraData.(*ChessMatchPool)
	}
	if !ok || cmp == nil {
		logger.Logger.Errorf("ChessMatchFunc not found ChessMatchPool")
		return nil
	}

	if p.IsRobot() || len(cmp.List) == 0 {
		return nil
	}

	var rule *server.DB_ChessMatchRules
	for _, v := range srvdata.PBDB_ChessMatchRulesMgr.Datas.Arr {
		switch {
		case p.ChessGrade >= int64(v.ScoreMin) && p.ChessGrade <= int64(v.ScoreMax):
			rule = v
		}
	}

	if rule == nil {
		logger.Logger.Tracef("ChessMatchFunc ChessMatchRule not found %d", p.ChessGrade)
		return nil
	}

	if cmp == nil {
		logger.Logger.Tracef("ChessMatchFunc ChessMatchPool is nil")
		return nil
	}

	if rule.MatchScoreMin > rule.MatchScoreMax {
		logger.Logger.Tracef("ChessMatchFunc rule.MatchScoreMin > rule.MatchScoreMax")
		return nil
	}

	var scene *Scene

	i := sort.Search(len(cmp.List), func(i int) bool {
		return cmp.List[i].Score >= int64(rule.MatchScoreMin)
	})
	j := sort.Search(len(cmp.List), func(i int) bool {
		return cmp.List[i].Score > int64(rule.MatchScoreMax)
	})
	if i > j {
		return nil
	}

	logger.Logger.Tracef("ChessMatchFunc 基础匹配范围 %d,%d", rule.MatchScoreMin, rule.MatchScoreMax)

	f := func(sceneId int) bool {
		s := SceneMgrSingleton.GetScene(sceneId)
		// 满人，解散中，排除
		if s == nil || s.IsFull() || s.deleting || common.InSliceInt32(exclude, int32(s.sceneId)) {
			return false
		}
		// 同IP限制
		if sameIpLimit && p.GMLevel == 0 && s.HasSameIp(p.Ip) {
			return false
		}
		// 同局限制
		if s.dbGameFree.GetSamePlaceLimit() > 0 && sceneLimitMgr.LimitSamePlace(p, s) {
			return false
		}

		return true
	}

	// 基础匹配
	if i < len(cmp.List) {
		for _, v := range cmp.List[i:j] {
			if f(v.SceneId) {
				logger.Logger.Tracef("ChessMatchFunc 基础匹配成功 %d playerScore:%d, other:%d", v.SceneId, p.ChessGrade, v.Score)
				scene = SceneMgrSingleton.GetScene(v.SceneId)
				break
			}
		}
	}

	// 扩展匹配
	if scene == nil {
		for k, v := range rule.MatchScoreLowStep {
			m := sort.Search(len(cmp.List), func(i int) bool {
				return cmp.List[i].Score >= int64(rule.MatchScoreMin-v)
			})
			n := sort.Search(len(cmp.List), func(i int) bool {
				return cmp.List[i].Score > int64(rule.MatchScoreMax+rule.MatchScoreHightStep[k])
			})
			logger.Logger.Tracef("ChessMatchFunc 扩展匹配范围 %d,%d", rule.MatchScoreMin-v, rule.MatchScoreMax+rule.MatchScoreHightStep[k])
			logger.Logger.Tracef("ChessMatchFunc 范围索引 m:%d, i:%d, j:%d, n:%d", m, i, j, n)
			// [m,n]的范围应该是包含[i,j]
			if m > i || j > n {
				// 配置错误
				break
			}

			if m >= 0 && m < i {
				for _, v := range cmp.List[m:i] {
					if f(v.SceneId) {
						logger.Logger.Tracef("ChessMatchFunc 扩展匹配成功 %d playerScore:%d, other:%d", v.SceneId, p.ChessGrade, v.Score)
						scene = SceneMgrSingleton.GetScene(v.SceneId)
						break
					}
				}
			}
			if scene == nil {
				if n >= j {
					for _, v := range cmp.List[j:n] {
						if f(v.SceneId) {
							logger.Logger.Tracef("ChessMatchFunc 扩展匹配成功 %d playerScore:%d, other:%d", v.SceneId, p.ChessGrade, v.Score)
							scene = SceneMgrSingleton.GetScene(v.SceneId)
							break
						}
					}
				}
			}
			if scene == nil {
				i = m
				j = n
			} else {
				break
			}
		}
	}

	return scene
}

func ChessMatchFuncTest(chessMatchPool *ChessMatchPool, chessScore int32) *Scene {
	var rule *server.DB_ChessMatchRules
	for _, v := range srvdata.PBDB_ChessMatchRulesMgr.Datas.Arr {
		switch {
		case chessScore >= v.ScoreMin && chessScore <= v.ScoreMax:
			rule = v
		}
	}

	if rule == nil {
		fmt.Printf("ChessMatchFunc ChessMatchRule not found %d\n", chessScore)
		return nil
	}

	if rule.MatchScoreMin > rule.MatchScoreMax {
		fmt.Printf("ChessMatchFunc rule.MatchScoreMin > rule.MatchScoreMax\n")
		return nil
	}

	var scene *Scene

	i := sort.Search(len(chessMatchPool.List), func(i int) bool {
		return chessMatchPool.List[i].Score >= int64(rule.MatchScoreMin)
	})
	j := sort.Search(len(chessMatchPool.List), func(i int) bool {
		return chessMatchPool.List[i].Score > int64(rule.MatchScoreMax)
	})
	if i > j {
		return nil
	}

	fmt.Printf("ChessMatchFunc 基础匹配范围 %d,%d\n", rule.MatchScoreMin, rule.MatchScoreMax)
	fmt.Printf("ChessMatchFunc 基础匹配范围 i:%d,j:%d\n", i, j)

	// 基础匹配
	if i < len(chessMatchPool.List) {
		for _, v := range chessMatchPool.List[i:j] {
			fmt.Printf("ChessMatchFunc 基础匹配成功 %d playerScore:%d, other:%d\n", v.SceneId, chessScore, v.Score)
		}
	}

	// 扩展匹配
	if scene == nil {
		for k, v := range rule.MatchScoreLowStep {
			m := sort.Search(len(chessMatchPool.List), func(i int) bool {
				return chessMatchPool.List[i].Score >= int64(rule.MatchScoreMin-v)
			})
			n := sort.Search(len(chessMatchPool.List), func(i int) bool {
				return chessMatchPool.List[i].Score > int64(rule.MatchScoreMax+rule.MatchScoreHightStep[k])
			})
			fmt.Printf("ChessMatchFunc 扩展匹配范围 %d,%d\n", rule.MatchScoreMin-v, rule.MatchScoreMax+rule.MatchScoreHightStep[k])
			fmt.Printf("ChessMatchFunc 范围索引 m:%d, i:%d, j:%d, n:%d\n", m, i, j, n)
			// [m,n]的范围应该是包含[i,j]
			if m > i || j > n {
				// 配置错误
				break
			}

			if m >= 0 && m < i {
				for _, v := range chessMatchPool.List[m:i] {
					fmt.Printf("ChessMatchFunc 扩展匹配成功 %d playerScore:%d, other:%d\n", v.SceneId, chessScore, v.Score)
				}
			}
			if scene == nil {
				if n >= j {
					for _, v := range chessMatchPool.List[j:n] {
						fmt.Printf("ChessMatchFunc 扩展匹配成功 %d playerScore:%d, other:%d\n", v.SceneId, chessScore, v.Score)
					}
				}
			}
			if scene == nil {
				i = m
				j = n
			} else {
				break
			}
		}
	}
	return nil
}
