package chess

import (
	"errors"
	"fmt"
	mergeDataCfg "server/conf/merge_data"
	startMergeCfg "server/conf/start_merge"
	userCfg "server/conf/user"
	"server/game/mod/item"
	GoUtil "server/game_util"
	"server/msg"
	"sort"
	"strings"
)

const (
	ModuleName                = "chess"
	ChessBoradMaxNum          = 63
	CHESS_ENERGY_CHEST        = 562
	CHESS_SURPRISE_CHEST_LOCK = 563
	CHESS_SURPRISE_CHEST      = 564
	CHESS_ZIXUAN_CHEST        = 701 // 自选宝箱
	CHESS_HIGH_ZIXUAN_CHEST   = 702 // 高级自选宝箱
	CHESS_TREASURE_CHEST      = 703 // 宝藏宝箱
	CHESS_HIGH_TREASURE_CHEST = 704 // 高级宝藏宝箱
	CHESS_SOURCE_CHEST        = 705 // 资源补给箱
	CHESS_HIGH_SOURCE_CHEST   = 706 // 高级资源补给箱
	CHESS_SEPARATE            = 707 // 分解器
	CHESS_UPGRADE             = 708 // 升级器
)

const (
	EMIT_RETIRE_START = 1
	EMIT_RETIRE_ING   = 2
	EMIT_RETIRE_END   = 3
)

type ChessBorad struct {
	ChessList      []int
	EmitList       map[int]int
	ChessBuff      []int
	ChessBag       ChessBag
	PartBag        PartBag
	ChessMap       map[string]int32
	Honor          map[int]int    // 荣誉室
	Retire         map[string]int // 退役发射器系列
	RetireReward   map[string]bool
	RetireChessMap map[string][]int
}

type PartBag struct {
	List map[int]PartBagGrid // 零件背包
}
type ChessBag struct {
	List map[int]ChessBagGrid
	Buy  int
	Free int
}

type ChessBagGrid struct {
	ChessId int // 棋子id
	EmitId  int // 发射器id
}

type PartBagGrid struct {
	PartId int // 零件id
	Num    int // 零件数量
}

func (cb *ChessBorad) IsEmpty() bool {
	cb.ver()
	return len(cb.ChessList) == 0
}

// 初始化棋盘
func (cb *ChessBorad) InitData() {
	StartMerge := startMergeCfg.GetStartChessList()
	cb.EmitList = make(map[int]int)
	cb.ChessList = StartMerge
	if cb.ChessBag.List == nil {
		cb.ChessBag.List = make(map[int]ChessBagGrid)
		InitNum := mergeDataCfg.GetChessBagInitNum()
		for i := 1; i <= InitNum; i++ {
			cb.ChessBag.List[i] = ChessBagGrid{}
		}
	}
	if cb.RetireReward == nil {
		cb.RetireReward = make(map[string]bool)
	}
	if cb.PartBag.List == nil {
		cb.PartBag.List = make(map[int]PartBagGrid)
	}
	if cb.ChessMap == nil {
		cb.ChessMap = make(map[string]int32)
	}
	if cb.RetireChessMap == nil {
		cb.RetireChessMap = make(map[string][]int)
	}
	if cb.Retire == nil {
		cb.Retire = make(map[string]int)
	}
	if cb.Honor == nil {
		cb.Honor = make(map[int]int)
	}
}

func (cb *ChessBorad) ver() {
	if cb.EmitList == nil {
		cb.EmitList = make(map[int]int)
	}
	if cb.ChessBag.List == nil {
		cb.ChessBag.List = make(map[int]ChessBagGrid)
		InitNum := mergeDataCfg.GetChessBagInitNum()
		for i := 1; i <= InitNum; i++ {
			cb.ChessBag.List[i] = ChessBagGrid{}
		}
	}
	if cb.RetireReward == nil {
		cb.RetireReward = make(map[string]bool)
	}
	if cb.PartBag.List == nil {
		cb.PartBag.List = make(map[int]PartBagGrid)
	}
	if cb.ChessMap == nil {
		cb.ChessMap = make(map[string]int32)
	}
	if cb.RetireChessMap == nil {
		cb.RetireChessMap = make(map[string][]int)
	}
	if cb.Retire == nil {
		cb.Retire = make(map[string]int)
	}
	if cb.Honor == nil {
		cb.Honor = make(map[int]int)
	}
}

func (cb *ChessBorad) GetChessBuf() []int {
	return cb.ChessBuff
}

// 棋子合成
func (cb *ChessBorad) ComposeChess(id int) (int, error) {
	CfgRecord, err := mergeDataCfg.GetOne(id)
	if err != nil {
		return 0, errors.New("配置错误")
	}
	if CfgRecord.Lv == CfgRecord.MaxLv {
		return 0, errors.New("已达最大等级")
	}
	count := 0
	newList := make([]int, 0, len(cb.ChessList))
	for _, chess := range cb.ChessList {
		if chess == id && count < 2 {
			count++
			continue
		}
		newList = append(newList, chess)
	}

	if count < 2 {
		return 0, errors.New("次数不足" + fmt.Sprintf("Id: %d", id))
	}
	ChessType := mergeDataCfg.GetTypeById(id)
	if ChessType == "Emitter" {
		cb.EmitList[id+1]++
		cb.EmitList[id] -= 2
	}
	id++
	newList = append(newList, id)

	cb.ChessList = newList
	return id, nil
}

func (cb *ChessBorad) GetChessList() []int {
	return cb.ChessList
}

// 获取解锁棋子列表
func (cb *ChessBorad) GetUnlockChessList() []int {
	r := make([]int, 0, len(cb.ChessList))
	for k, v := range cb.ChessMap {
		arr := strings.Split(k, "@")
		if arr[2] == "0" {
			r = append(r, int(v))
		}
	}
	return r
}

// 添加棋子
func (cb *ChessBorad) AddChess(id int) error {
	_, err := mergeDataCfg.GetOne(id)
	if err != nil {
		return errors.New("配置错误")
	}
	if len(cb.ChessList)+1 > ChessBoradMaxNum { // 棋盘满了 加入缓存区
		cb.ChessBuff = append(cb.ChessBuff, id)
		return nil
	}
	ChessType := mergeDataCfg.GetTypeById(id)
	if ChessType == "Emitter" {
		cb.EmitList[id]++
	}
	cb.ChessList = append(cb.ChessList, id)
	return nil
}

// 购买棋子
func (cb *ChessBorad) BuyChess(id int) (int, error) {
	CfgRecord, err := mergeDataCfg.GetOne(id)
	if err != nil {
		return 0, errors.New("配置错误")
	}
	cb.ChessList = append(cb.ChessList, id)
	ChessType := mergeDataCfg.GetTypeById(id)
	if ChessType == "Emitter" {
		cb.EmitList[id]++
	}
	return CfgRecord.SellNum, nil
}

// 出售棋子
func (cb *ChessBorad) SellChess(id int) ([]*item.Item, error) {
	CfgRecord, err := mergeDataCfg.GetOne(id)
	if err != nil {
		return nil, errors.New("配置错误")
	}
	count := 0
	newList := make([]int, 0, len(cb.ChessList))
	for _, chess := range cb.ChessList {
		if chess == id && count < 1 {
			count++
			continue
		}
		newList = append(newList, chess)
	}

	if count < 1 {
		return nil, errors.New("次数不足")
	}

	cb.ChessList = newList
	var items []*item.Item
	switch CfgRecord.SellType {
	case "star":
		items = append(items, &item.Item{Id: item.ITEM_STAR_ID, Num: CfgRecord.SellNum})
	case "diamond":
		items = append(items, &item.Item{Id: item.ITEM_DIAMOND_ID, Num: CfgRecord.SellNum})
	case "energy":
		items = append(items, &item.Item{Id: item.ITEM_ENERGY_ID, Num: CfgRecord.SellNum})
	case "Racing Battery":
		items = append(items, &item.Item{Id: item.ITEM_RACING_BATTERY_ID, Num: CfgRecord.SellNum})
	}
	return items, nil
}

// 移除棋子
func (cb *ChessBorad) RemoveChess(Id int) error {
	find := false
	for k, v := range cb.ChessList {
		if v == Id {
			cb.ChessList = append(cb.ChessList[:k], cb.ChessList[k+1:]...)
			find = true
			break
		}
	}
	if !find {
		return errors.New("chess id not exist")
	}
	ChessType := mergeDataCfg.GetTypeById(Id)
	if ChessType == "Emitter" {
		v, ok := cb.EmitList[Id]
		if v > 0 && ok {
			cb.EmitList[Id]--
		}
	}
	return nil
}

// emitListToSlice 将 EmitList 过滤并转换为发射器 ID 列表。
// retireFilter 为 true 时过滤已退役的发射器。
func (cb *ChessBorad) emitListToSlice(retireFilter bool) []int {
	EM := make(map[string]int)
	for k, v := range cb.EmitList {
		if v <= 0 {
			delete(cb.EmitList, k)
			continue
		}
		EmitID := mergeDataCfg.GetEmitId(k)
		if EmitID == "" {
			continue
		}
		if retireFilter && cb.Retire[EmitID] >= EMIT_RETIRE_START {
			continue
		}
		if mergeDataCfg.GetEmitType(k) == "sub" {
			continue
		}
		EM[EmitID] = max(EM[EmitID], k)
	}
	result := make([]int, 0, len(EM))
	for _, v := range EM {
		result = append(result, v)
	}
	return result
}

func (cb *ChessBorad) GetStarEmitList() []int {
	return cb.emitListToSlice(false)
}

func (cb *ChessBorad) GetEmitList() []int {
	return cb.emitListToSlice(true)
}

// 完成订单 移除棋子
func (cb *ChessBorad) FinishOrder(ChessId []int) error {
	unlockChessList := cb.GetUnlockChessList()
	unlockChessMap := make(map[int]int)
	for _, v := range unlockChessList {
		unlockChessMap[v]++
	}

	var boardChess []int
	var BagChess []int
	for _, v := range ChessId {
		if unlockChessMap[v] > 0 {
			unlockChessMap[v]--
			boardChess = append(boardChess, v)
		} else {
			BagChess = append(BagChess, v)
		}
	}
	for _, v := range boardChess {
		err := cb.FinishOrderChess(v)
		if err != nil {
			return err
		}
	}
	for _, v := range BagChess {
		err := cb.FinishOrderChessByBag(v)
		if err != nil {
			return err
		}
	}
	return nil
}

// 完成订单 移除棋子
func (cb *ChessBorad) FinishOrderChess(Chess int) error {
	for k, v := range cb.ChessList {
		if v == Chess {
			cb.ChessList = append(cb.ChessList[:k], cb.ChessList[k+1:]...)
			return nil
		}
	}
	return fmt.Errorf("order finish board chess id：%d not exist", Chess)
}

// 完成订单 移除棋子
func (cb *ChessBorad) FinishOrderChessByBag(Chess int) error {
	for k, v := range cb.ChessBag.List {
		if v.ChessId == Chess {
			cb.ChessBag.List[k] = ChessBagGrid{}
			return nil
		}
	}
	return fmt.Errorf("order finish bag chess id：%d not exist", Chess)
}

// 棋子转换
func (cb *ChessBorad) ExChess(OldChessId, NewChessId int) error {
	if OldChessId > 0 {
		newList, b := GoUtil.PopElemSlice(cb.ChessList, OldChessId)
		if !b {
			return fmt.Errorf("ExChess chess id not exist")
		}
		cb.ChessList = newList
	}
	return cb.AddChess(NewChessId)
}

// 增加棋盘缓冲器
func (cb *ChessBorad) AddChessBuff(chess int) {
	cb.ChessBuff = append(cb.ChessBuff, chess)
}

func (cb *ChessBorad) AddHonor(Id int) {
	cb.Honor[Id] = 1
}

func (cb *ChessBorad) RemoveHonor(Id int) {
	delete(cb.Honor, Id)
}

// 从暂存区添加棋子到棋盘
func (cb *ChessBorad) GetChessFromBuff(Chess int) error {
	for i, v := range cb.ChessBuff {
		if v == Chess {
			cb.ChessBuff = append(cb.ChessBuff[:i], cb.ChessBuff[i+1:]...)
			return cb.AddChess(Chess)
		}
	}
	return errors.New("chess id not exist")
}

// 扣除零件
func (cb *ChessBorad) LosePart(PartId int, Num int) error {
	v, ok := cb.PartBag.List[PartId]
	if !ok || v.Num < Num {
		return errors.New("part id not exist or num not enough" + fmt.Sprintf("PartId: %d, Num: %d, ok: %v", PartId, Num, ok))
	}
	v.Num -= Num
	cb.PartBag.List[PartId] = v
	return nil
}

// 返回数据
func (cb *ChessBorad) BackData() *msg.ResPlayerChessInfo {
	var ChessBagGrids []*msg.ChessBagGrid
	for k, v := range cb.ChessBag.List {
		ChessBagGrids = append(ChessBagGrids, &msg.ChessBagGrid{
			Id:      int32(k),
			ChessId: int32(v.ChessId),
			EmitId:  int32(v.EmitId),
		})
	}
	var PartBagGrids []*msg.PartBagGrid
	for k, v := range cb.PartBag.List {
		PartBagGrids = append(PartBagGrids, &msg.PartBagGrid{
			PartId: int32(k),
			Count:  int32(v.Num),
		})
	}
	Re := make([]string, 0, len(cb.Retire))
	for k, v := range cb.Retire {
		if v == EMIT_RETIRE_END {
			Re = append(Re, k)
		}
	}
	Ho := make([]int32, 0, len(cb.Honor))
	for k := range cb.Honor {
		Ho = append(Ho, int32(k))
	}
	Rw := make([]string, 0, len(cb.RetireReward))
	for k, v := range cb.RetireReward {
		if v {
			Rw = append(Rw, k)
		}
	}
	return &msg.ResPlayerChessInfo{
		ChessList:    GoUtil.SliceIntToInt32(cb.ChessList),
		ChessBuff:    GoUtil.SliceIntToInt32(cb.ChessBuff),
		RetireEmit:   Re,
		RetireReward: Rw,
		Honor:        Ho,
		ChessBag: &msg.ChessBag{
			ChessBagGrids: ChessBagGrids,
			ChessBuyCnt:   int32(cb.ChessBag.Buy),
			ChessFreeCnt:  int32(cb.ChessBag.Free),
		},
		PartBag: &msg.PartBag{
			PartBagGrids: PartBagGrids,
		},
	}
}

// 解锁棋盘背包
func (cb *ChessBorad) BuyChessBagGrid() error {
	if cb.ChessBag.Free > 0 {
		cb.ChessBag.List[len(cb.ChessBag.List)+1] = ChessBagGrid{}
		cb.ChessBag.Free--
		return nil
	}
	MaxBuy := mergeDataCfg.GetChessBagBugNum()
	if cb.ChessBag.Buy >= MaxBuy {
		return fmt.Errorf("ChessBag can buy is full")
	}
	cb.ChessBag.Buy++
	cb.ChessBag.List[len(cb.ChessBag.List)+1] = ChessBagGrid{}
	return nil
}

func (cb *ChessBorad) GetBuyChessBagGridCost() []*item.Item {
	if cb.ChessBag.Free > 0 {
		return nil
	}
	NeedDiamond := 10 + 15*cb.ChessBag.Buy
	return []*item.Item{{Id: item.ITEM_DIAMOND_ID, Num: -NeedDiamond}}
}

// 升级触发解锁棋盘背包
func (cb *ChessBorad) TriggerChessBagUnlock(Lv int) bool {
	UnlockPack := userCfg.GetUnlockPack(Lv)
	if UnlockPack > 0 {
		cb.ChessBag.Free += UnlockPack
		return true
	}
	return false
}

// 将棋子放入背包
func (cb *ChessBorad) PutChessInBag(Grid, ChessId, EmitId int) error {
	err := cb.RemoveChess(ChessId)
	if err != nil {
		return err
	}
	if Grid == 0 { // 背包id为0且发射器已退役奖励已领取 直接放入荣誉室
		cb.AddHonor(ChessId)
		return nil
	}
	v, ok := cb.ChessBag.List[Grid]
	if !ok {
		return errors.New("ChessBag Grid unlock")
	}

	if v.ChessId > 0 {
		return errors.New("ChessBag Grid is not empty")
	}
	cb.ChessBag.List[Grid] = ChessBagGrid{
		ChessId: ChessId,
		EmitId:  EmitId,
	}
	return nil
}

// 将零件放入背包
func (cb *ChessBorad) PutPartInBag(ChessId int) error {
	err := cb.RemoveChess(ChessId)
	if err != nil {
		return err
	}
	ChessLv := mergeDataCfg.GetLvById(ChessId)
	ChessMaxLv := mergeDataCfg.GetMaxLvById(ChessId)
	if ChessLv != ChessMaxLv { // 零件只能放入满级棋子
		return errors.New("part Lv is not max")
	}
	if cb.PartBag.List == nil {
		cb.PartBag.List = make(map[int]PartBagGrid)
	}
	Num := cb.PartBag.List[ChessId].Num
	cb.PartBag.List[ChessId] = PartBagGrid{
		PartId: ChessId,
		Num:    Num + 1,
	}
	return nil
}

// 将棋子从背包取出
func (cb *ChessBorad) TakeChessOutBag(Grid int) (int, error) {
	if Grid < 0 {
		cb.RemoveHonor(-Grid)
		cb.AddChess(-Grid)
		return 0, nil
	}
	GridInfo, ok := cb.ChessBag.List[Grid]
	if !ok {
		return 0, errors.New("ChessBag Grid unlock")
	}
	if GridInfo.ChessId == 0 {
		return 0, errors.New("ChessBag Grid is empty")
	}
	cb.ChessBag.List[Grid] = ChessBagGrid{}
	return GridInfo.ChessId, cb.AddChess(GridInfo.ChessId)
}

func (cb *ChessBorad) GetOrderEmit() []int {
	return cb.GetEmitList()
}

func (cb *ChessBorad) GetRetireEmit() map[string]int {
	return cb.Retire
}

// 获取退役发射器的棋子列表
func (cb *ChessBorad) GetRetireChess(EmitType string) []int {
	v, ok := cb.RetireChessMap[EmitType]
	if !ok {
		return nil
	}
	if len(v) == 1 {
		cb.RetireChessMap[EmitType] = nil
		return v
	}
	if len(v) == 0 {
		return nil
	}
	cb.RetireChessMap[EmitType] = v[2:]
	return v[:2]
}

// 开始退役
func (cb *ChessBorad) BeginRetire(EmitType string) error {
	if cb.Retire == nil {
		cb.Retire = make(map[string]int)
	}
	_, ok := cb.Retire[EmitType]
	if ok {
		return errors.New("chess has been retired")
	}
	cb.Retire[EmitType] = EMIT_RETIRE_START
	return nil
}

// 退役棋子处理
func (cb *ChessBorad) RetireOrder(EmitType string) error {
	if cb.Retire[EmitType] != 1 {
		return errors.New("chess has not been retired")
	}
	chess := make([]int, 0, len(cb.ChessMap))
	EmitProduct := mergeDataCfg.GetEmitOrderProduce(EmitType)
	for k, v := range cb.ChessMap {
		arr := strings.Split(k, "@")
		Color := mergeDataCfg.GetColorById(int(v))
		if arr[2] == "0" && GoUtil.InStringArray(Color, EmitProduct) {
			chess = append(chess, int(v))
		}
	}

	sort.Sort(sort.Reverse(sort.IntSlice(chess)))
	cb.RetireChessMap[EmitType] = chess
	cb.Retire[EmitType] = EMIT_RETIRE_ING
	return nil
}

// 完成退役
func (cb *ChessBorad) FinishRetire(EmitType string) error {
	_, ok := cb.Retire[EmitType]
	if !ok {
		return errors.New("chess has not been retired")
	}
	cb.Retire[EmitType] = EMIT_RETIRE_END
	return nil
}

// 获取资源宝箱奖励
func (cb *ChessBorad) SourceChest(ChessId int) ([]*item.Item, error) {
	err := cb.RemoveChess(ChessId)
	if err != nil {
		return nil, err
	}
	if ChessId == CHESS_SOURCE_CHEST {
		return mergeDataCfg.GetSourceChestItem(), nil
	}
	if ChessId == CHESS_HIGH_SOURCE_CHEST {
		return mergeDataCfg.GetHighSourceChestItem(), nil
	}

	return nil, nil
}

// 降低棋子等级
func (cb *ChessBorad) SeparateChess(ChessId int) (int, error) {
	ChessLv := mergeDataCfg.GetLvById(ChessId)
	if ChessLv == 1 {
		return 0, errors.New("chess lv is 1")
	}
	ChessType := mergeDataCfg.GetTypeById(ChessId)
	if ChessType != "Product" {
		return 0, errors.New("chess type is not product")
	}
	err := cb.RemoveChess(ChessId)
	if err != nil {
		return 0, err
	}
	err = cb.RemoveChess(CHESS_SEPARATE)
	if err != nil {
		return 0, err
	}
	ChessColor := mergeDataCfg.GetColorById(ChessId)
	NewChess := mergeDataCfg.GetChessIdByLvAndColor(ChessLv-1, ChessColor)
	cb.AddChess(NewChess)
	cb.AddChess(NewChess)
	return NewChess, nil
}

// 提高棋子等级
func (cb *ChessBorad) UpgradeChess(ChessId int) (int, error) {
	ChessLv := mergeDataCfg.GetLvById(ChessId)
	ChessMaxLv := mergeDataCfg.GetMaxLvById(ChessId)
	if ChessLv == ChessMaxLv {
		return 0, errors.New("chess lv is max")
	}
	ChessType := mergeDataCfg.GetTypeById(ChessId)
	if ChessType != "Product" {
		return 0, errors.New("chess type is not product")
	}
	err := cb.RemoveChess(ChessId)
	if err != nil {
		return 0, err
	}
	err = cb.RemoveChess(CHESS_UPGRADE)
	if err != nil {
		return 0, err
	}
	NewChess := mergeDataCfg.GetChessIdByLvAndColor(ChessLv+1, mergeDataCfg.GetColorById(ChessId))
	cb.AddChess(NewChess)
	return NewChess, nil
}

func (cb *ChessBorad) GetPartBag() map[int]int {
	res := make(map[int]int)
	for k, v := range cb.PartBag.List {
		res[k] = v.Num
	}
	return res
}

func (cb *ChessBorad) GetRetireReward(Id string) ([]*item.Item, error) {
	if cb.RetireReward[Id] == true {
		return nil, errors.New("emit retire reward has been get")
	}
	if cb.Retire[Id] != EMIT_RETIRE_END {
		return nil, errors.New("emit not finish retire")
	}
	cb.RetireReward[Id] = true
	return mergeDataCfg.GetRetireReward(), nil
}
