package chess

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

const (
	ModuleName              = "chess"
	ChessBoradMaxNum        = 63
	CHESS_SOURCE_CHEST      = 705
	CHESS_HIGH_SOURCE_CHEST = 706
	CHESS_SEPARATE          = 707 // 分解器
)

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

type ChessBag struct {
	List map[int]ChessBagGrid
	Buy  int
	Free int
}

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

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{}
		}
	}
}

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.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) 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)
	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]--
		cb.EmitList[id]--
	}
	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) GetUnlockChessList() []int {
// 	return cb.ChessBag.List
// }

// 添加棋子
func (cb *ChessBorad) AddChess(id int) error {
	_, err := mergeDataCfg.GetOne(id)
	if err != nil {
		return errors.New("配置错误")
	}
	NewChessList := append(cb.ChessList, id)
	if len(NewChessList) > 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})
	}
	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
}

func (cb *ChessBorad) GetEmitList() []int {
	result := make([]int, 0, len(cb.EmitList))
	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 cb.Retire[EmitID] == 2 {
			continue
		}
		EmitType := mergeDataCfg.GetEmitType(k)
		if EmitType == "sub" {
			continue
		}
		if v > 0 {
			EM[EmitID] = max(EM[EmitID], k)
		}
	}
	for _, v := range EM {
		result = append(result, v)
	}
	return result
}

// 完成订单 移除棋子
func (cb *ChessBorad) FinishOrder(ChessId []int) error {
	for _, v := range ChessId {
		err := cb.FinishOrderChess(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
		}
	}
	for k, v := range cb.ChessBag.List {
		if v.ChessId == Chess {
			cb.ChessBag.List[k] = ChessBagGrid{}
			return nil
		}
	}
	return errors.New("order finish chess id not exist")
}

// 棋子转换
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:]...)
			cb.AddChess(Chess)
			return nil
		}
	}
	return errors.New("chess id not exist")
}

// 返回数据
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),
		})
	}
	Re := make([]string, 0)
	for k, v := range cb.Retire {
		if v == 3 {
			Re = append(Re, k)
		}
	}
	Ho := make([]int32, 0)
	for k := range cb.Honor {
		Ho = append(Ho, int32(k))
	}
	return &msg.ResPlayerChessInfo{
		ChessList:  GoUtil.SliceIntToInt32(cb.ChessList),
		ChessBuff:  GoUtil.SliceIntToInt32(cb.ChessBuff),
		RetireEmit: Re,
		Honor:      Ho,
		ChessBag: &msg.ChessBag{
			ChessBagGrids: ChessBagGrids,
			ChessBuyCnt:   int32(cb.ChessBag.Buy),
			ChessFreeCnt:  int32(cb.ChessBag.Free),
		},
	}
}

// 解锁棋盘背包
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
	}
	EmitColorId := mergeDataCfg.GetEmitId(ChessId)
	ChessLv := mergeDataCfg.GetLvById(ChessId)
	ChessMaxLv := mergeDataCfg.GetMaxLvById(ChessId)
	if ChessLv == ChessMaxLv && cb.Retire[EmitColorId] == 3 { // 退役发射器 加入荣誉室
		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) TakeChessOutBag(Grid int) error {
	if Grid < 0 {
		cb.RemoveHonor(-Grid)
		cb.AddChess(-Grid)
		return nil
	}
	GridInfo, ok := cb.ChessBag.List[Grid]
	if !ok {
		return errors.New("ChessBag Grid unlock")
	}
	if GridInfo.ChessId == 0 {
		return errors.New("ChessBag Grid is empty")
	}
	cb.ChessBag.List[Grid] = ChessBagGrid{}
	return 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 {
	_, ok := cb.Retire[EmitType]
	if ok {
		return errors.New("chess has been retired")
	}
	cb.Retire[EmitType] = 1
	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)
	EmitProduct := mergeDataCfg.GetEmitProduce(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] = 2
	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] = 3
	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) error {
	ChessLv := mergeDataCfg.GetLvById(ChessId)
	if ChessLv == 1 {
		return errors.New("chess lv is 1")
	}
	ChessType := mergeDataCfg.GetTypeById(ChessId)
	if ChessType != "Product" {
		return errors.New("chess type is not product")
	}
	err := cb.RemoveChess(ChessId)
	if err != nil {
		return err
	}
	err = cb.RemoveChess(CHESS_SEPARATE)
	if err != nil {
		return err
	}
	ChessColor := mergeDataCfg.GetColorById(ChessId)
	NewChess := mergeDataCfg.GetChessIdByLvAndColor(ChessLv-1, ChessColor)
	cb.AddChess(NewChess)
	cb.AddChess(NewChess)
	return nil
}
