package order

import (
	"server/GoUtil"
	mergeDataCfg "server/conf/mergeData"
	orderCfg "server/conf/order"
	userCfg "server/conf/user"
)

var reflectChess = map[int]int{} // 棋子难度映射表

// 订单棋子数量
func getChessNumRand(OrderN int) map[int]int {
	return map[int]int{
		1: int(15 - 3*OrderN),
		2: int(50 + OrderN),
		3: int(35 + 2*OrderN),
	}
}

// 根据上一个订单难度和系数 生成订单难度
func getOrderDiffRand(Diff, OrderN int) map[int]int {
	var d map[int]int
	switch Diff {
	case DIFF_LOW:
		d = map[int]int{
			DIFF_LOW:  int(10 - OrderN),
			DIFF_MID:  int(30),
			DIFF_HIGH: int(60 + OrderN),
		}
	case DIFF_MID:
		d = map[int]int{
			DIFF_LOW:  int(21 - 3*OrderN),
			DIFF_MID:  int(49 + 1.5*float64(OrderN)),
			DIFF_HIGH: int(30 + 1.5*float64(OrderN)),
		}
	case DIFF_HIGH:
		d = map[int]int{
			DIFF_LOW:  int(60 - 5*OrderN),
			DIFF_MID:  int(30 + 3*float64(OrderN)),
			DIFF_HIGH: int(10 + 2*float64(OrderN)),
		}
	}
	return d
}

// 根据订单难度生成棋子难度
func getChessDiff(ChessNum, OrderDiff, OrderN int) map[int]int {
	var rs map[int]int
	switch ChessNum {
	case 1:
		rs = map[int]int{
			1: OrderDiff,
		}
	case 2:
		switch OrderDiff {
		case DIFF_LOW:
			rand := map[int]int{
				DIFF_LOW: 99 - OrderN,
				DIFF_MID: 1 + OrderN,
			}
			secondDiff := GoUtil.RandMap(rand)
			rs = map[int]int{
				1: DIFF_LOW,
				2: secondDiff,
			}
		case DIFF_MID:
			rand := map[int]int{
				DIFF_LOW: 5 + OrderN,
				DIFF_MID: 95 - OrderN,
			}
			secondDiff := GoUtil.RandMap(rand)
			rs = map[int]int{
				1: DIFF_LOW,
				2: secondDiff,
			}
		case DIFF_HIGH:
			rand := map[int]int{
				DIFF_LOW:  int(95 - 10*OrderN),
				DIFF_MID:  int(4 + 6*OrderN),
				DIFF_HIGH: int(1 + 4*OrderN),
			}
			secondDiff := GoUtil.RandMap(rand)
			rs = map[int]int{
				1: DIFF_LOW,
				2: secondDiff,
			}
		}
	case 3:
		switch OrderDiff {
		case DIFF_LOW:
			rand := map[int]int{
				DIFF_LOW: 95 - OrderN,
				DIFF_MID: 5 + OrderN,
			}
			secondDiff := GoUtil.RandMap(rand)
			rand = map[int]int{
				DIFF_LOW: 60 - 4*OrderN,
				DIFF_MID: 40 + 4*OrderN,
			}
			thirdDiff := GoUtil.RandMap(rand)
			rs = map[int]int{
				1: DIFF_LOW,
				2: secondDiff,
				3: thirdDiff,
			}
		case DIFF_MID:
			rand := map[int]int{
				DIFF_LOW: 50 - 3*OrderN,
				DIFF_MID: 50 + 3*OrderN,
			}
			secondDiff := GoUtil.RandMap(rand)
			rand = map[int]int{
				DIFF_MID:  95 - 4*OrderN,
				DIFF_HIGH: 5 + 4*OrderN,
			}
			thirdDiff := GoUtil.RandMap(rand)
			rs = map[int]int{
				1: DIFF_LOW,
				2: secondDiff,
				3: thirdDiff,
			}
		case DIFF_HIGH:
			rand := map[int]int{
				DIFF_LOW: int(95 - 10*OrderN),
				DIFF_MID: int(5 + 10*OrderN),
			}
			secondDiff := GoUtil.RandMap(rand)
			rand = map[int]int{
				DIFF_MID:  int(95 - 8*OrderN),
				DIFF_HIGH: int(5 + 8*OrderN),
			}
			thirdDiff := GoUtil.RandMap(rand)
			rs = map[int]int{
				1: DIFF_LOW,
				2: secondDiff,
				3: thirdDiff,
			}
		}
	}
	return rs
}

// 根据难度生成棋子等级
func getChessLv(Min, Max, Diff int) int {
	Start := Min
	End := Max
	switch Diff {
	case DIFF_LOW:
		End = Min + (Max-Min+1)/3 - 1
	case DIFF_MID:
		Start = Min + (Max-Min+1)/3
		End = Min + (Max-Min+1)/3*2 - 1
	case DIFF_HIGH:
		Start = Min + (Max-Min+1)/3*2
	}
	Start = max(Min, Start)
	End = max(Start, End)
	End = min(Max, End)
	return GoUtil.RandNum(Start, End)
}

// 宝箱雨随机棋子类型
func RandChessColor(Emit []int) string {
	r := make(map[string]int)
	for _, v := range Emit {
		Produce := mergeDataCfg.GetEmitProduceType(v)
		if len(Produce) == 0 {
			continue
		}
		if len(Produce) == 1 {
			if Produce[0] == "" {
				continue
			}
			r[Produce[0]] = 100
			continue
		}
		r[Produce[0]] = 80
		r[Produce[1]] = 20
	}
	return GoUtil.RandStringMap(r)
}

// 获取棋子等级范围
func getChesslvRange(Emit int, EnergyMul int) (int, int) {
	RandEmitLv := mergeDataCfg.GetLvById(Emit)
	EmitId := mergeDataCfg.GetEmitId(Emit)
	RandMaxLv := mergeDataCfg.GetMaxLvById(Emit)
	RandEmitMinLv := mergeDataCfg.GetEmitMinLvById(EmitId)
	Ratio := mergeDataCfg.GetEmitRatio(EmitId)
	m := int(float64(1+RandEmitLv-RandEmitMinLv) / float64(1+RandMaxLv-RandEmitMinLv) / Ratio * 100)
	ChessMinLev := orderCfg.GetLvMin(EnergyMul)
	ChessMaxLev := orderCfg.GetLvMax(EnergyMul, m)
	return ChessMinLev, ChessMaxLev
}

// 根据类型获取发射器id
func GetEmitByColor(Emit []int, color string) int {
	for _, v := range Emit {
		Produce := mergeDataCfg.GetEmitProduceChessType(v)
		for _, c := range Produce {
			if c == color {
				return v
			}
		}
	}
	return 0
}

// 随机生成超级订单棋子
func randSuperOrderChess(o *OrderMod, lv int, Emit []int, EnergyMul int) ([]int, int, error) {
	initReflectChess(Emit, EnergyMul)
	filterPool(o)
	OrderN, err := userCfg.GetOrderNByLv(lv)
	RandChessNum := map[int]int{
		2: 70 - OrderN,
		3: 30 + OrderN,
	}
	if err != nil {
		return nil, DIFF_LOW, err
	}
	// 生成订单难度和棋子数量
	ChessNum := GoUtil.RandMap(RandChessNum)
	OrderDiff := DIFF_HIGH
	ChessDiff := getChessDiff(ChessNum, OrderDiff, OrderN)
	mergeList := make([]int, 0, len(ChessDiff))
	// 根据订单棋子难度生成棋子
	for _, v := range ChessDiff {
		ChessId := 0
		Num := 0
		for {
			Num++
			if Num > 50 {
				break
			}
			ChessId = getChessFromPoolByDiff(o, v, Emit, EnergyMul)
			if ChessId == 0 {
				continue
			}
			if !GoUtil.InArray(ChessId, mergeList) {
				break
			}
		}
		mergeList = append(mergeList, ChessId)
	}
	return mergeList, OrderDiff, nil
}

// 随机生成超级订单棋子
func randOrderChessWithDiff(o *OrderMod, lv int, Emit []int, EnergyMul, OrderDiff, ChessNum int) ([]int, int, error) {
	initReflectChess(Emit, EnergyMul)
	filterPool(o)
	OrderN, err := userCfg.GetOrderNByLv(lv)
	if err != nil {
		return nil, DIFF_LOW, err
	}
	ChessDiff := getChessDiff(ChessNum, OrderDiff, OrderN)
	mergeList := make([]int, 0, len(ChessDiff))
	// 根据订单棋子难度生成棋子
	for _, v := range ChessDiff {
		ChessId := 0
		Num := 0
		for {
			Num++
			if Num > 50 {
				break
			}
			ChessId = getChessFromPoolByDiff(o, v, Emit, EnergyMul)
			if ChessId == 0 {
				continue
			}
			if !GoUtil.InArray(ChessId, mergeList) {
				break
			}
		}
		mergeList = append(mergeList, ChessId)
	}
	return mergeList, OrderDiff, nil
}

// 随机生成订单棋子
func randOrderChess(o *OrderMod, lv int, Emit []int, EnergyMul int) ([]int, int, error) {
	initReflectChess(Emit, EnergyMul)
	filterPool(o)
	OrderN, err := userCfg.GetOrderNByLv(lv)
	RandChessNum := getChessNumRand(OrderN)
	if err != nil {
		return nil, DIFF_LOW, err
	}
	// 生成订单难度和棋子数量
	ChessNum := GoUtil.RandMap(RandChessNum)
	OrderDiffRand := getOrderDiffRand(o.LastDiff, OrderN)
	OrderDiff := GoUtil.RandMap(OrderDiffRand)
	ChessDiff := getChessDiff(ChessNum, OrderDiff, OrderN)
	mergeList := make([]int, 0, len(ChessDiff))
	// 根据订单棋子难度生成棋子
	for _, v := range ChessDiff {
		ChessId := 0
		Num := 0
		for {
			Num++
			if Num > 50 {
				break
			}
			ChessId = getChessFromPoolByDiff(o, v, Emit, EnergyMul)
			if ChessId == 0 {
				continue
			}
			if !GoUtil.InArray(ChessId, mergeList) {
				break
			}
		}
		mergeList = append(mergeList, ChessId)
	}
	return mergeList, OrderDiff, nil
}

// 筛选棋子池 从中剔除不符合难度的棋子
func filterPool(o *OrderMod) {
	NewPool := make([]int, 0)
	for _, v := range o.ChessPool {
		if _, ok := reflectChess[v]; ok {
			NewPool = append(NewPool, v)
		}
	}
	o.ChessPool = NewPool
}

// 获取发射器系列
func getEmitSeries(o *OrderMod, Emit []int) string {
	if o.EmitShuffle == nil {
		o.EmitShuffle = make([]string, 0)
		for _, v := range Emit {
			EmitProduct := mergeDataCfg.GetEmitProduceType(v)
			if len(EmitProduct) == 0 || EmitProduct[0] == "" {
				continue
			}
			EmitSerie := mergeDataCfg.GetEmitId(v)
			if GoUtil.InStringArray(EmitSerie, o.EmitShuffle) {
				continue
			}
			for i := 0; i < len(EmitProduct); i++ {
				o.EmitShuffle = append(o.EmitShuffle, EmitSerie)
			}
		}
		o.EmitShuffle = GoUtil.ShuffleStringArray(o.EmitShuffle)
	}
	PopEmitId, NewSlice := GoUtil.PopStringArray(o.EmitShuffle)
	o.EmitShuffle = NewSlice
	if len(o.EmitShuffle) == 0 {
		o.EmitShuffle = make([]string, 0)
		for _, v := range Emit {
			EmitProduct := mergeDataCfg.GetEmitProduceType(v)
			if len(EmitProduct) == 0 || EmitProduct[0] == "" {
				continue
			}
			EmitSerie := mergeDataCfg.GetEmitId(v)
			if GoUtil.InStringArray(EmitSerie, o.EmitShuffle) {
				continue
			}
			for i := 0; i < len(EmitProduct); i++ {
				o.EmitShuffle = append(o.EmitShuffle, EmitSerie)
			}
		}
		Num := 1
		for {
			o.EmitShuffle = GoUtil.ShuffleStringArray(o.EmitShuffle)
			if o.EmitShuffle[0] != PopEmitId {
				break
			}
			Num++
			if Num > 100 {
				break
			}
		}
	}
	return PopEmitId
}

// 订单能获取的宠物币
func getOrderStar(ChessList []int) int {
	Star := 0
	for _, v := range ChessList {
		Star += mergeDataCfg.GetStarById(v)
	}
	return Star
}

// 从棋子池中获取棋子
func getChessFromPoolByDiff(o *OrderMod, Diff int, Emit []int, EnergyMul int) int {
	EmitSeries := getEmitSeries(o, Emit)
	EmitChessId := getEmitBySeries(Emit, EmitSeries)
	ColorRand := mergeDataCfg.GetEmitProduceType(EmitChessId)
	// 从棋子池中获取棋子
	MinChessId := 0
	for i, chess := range o.ChessPool {
		chessColor := mergeDataCfg.GetColorById(chess)
		if reflectChess[chess] > Diff {
			MinChessId = chess
		}
		if !GoUtil.InStringArray(chessColor, ColorRand) {
			continue
		}
		ChessLv := mergeDataCfg.GetLvById(chess)
		if reflectChess[chess] == Diff && ChessLv >= EnergyMul+1 && ChessLv <= EnergyMul+12 {
			o.ChessPool = append(o.ChessPool[:i], o.ChessPool[i+1:]...)
			return chess
		}
	}
	/** 获取不到时选最接近的棋子
	 * 1. 选取最接近的棋子
	 */
	if MinChessId != 0 {
		MinChessColor := mergeDataCfg.GetColorById(MinChessId)
		NewEmitChessId := GetEmitByColor(Emit, MinChessColor)
		ColorRand := mergeDataCfg.GetEmitProduceType(NewEmitChessId)
		ChessMinLv, ChessMaxLv := getChesslvRange(NewEmitChessId, EnergyMul)
		NewLev := getChessLv(ChessMinLv, ChessMaxLv, Diff)
		MinChessLv := mergeDataCfg.GetLvById(MinChessId)
		NewLev2 := mergeDataCfg.DynamicLev2(NewLev, NewEmitChessId, ColorRand[0], MinChessColor)
		NewLev3 := adjustLev(NewLev2, EnergyMul)
		o.ChessPool = GoUtil.DeleteEleByValue(o.ChessPool, MinChessId)
		for i := NewLev3; i < MinChessLv; i++ {
			ChessId2 := mergeDataCfg.GetChessIdByLvAndColor(i, MinChessColor)
			if ChessId2 != 0 {
				o.ChessPool = append(o.ChessPool, ChessId2)
			}
		}
		Chess := mergeDataCfg.GetChessIdByLvAndColor(NewLev2, MinChessColor)
		return Chess
	}
	Color := GoUtil.RandStringSlice(ColorRand)
	ChessMinLv, ChessMaxLv := getChesslvRange(EmitChessId, EnergyMul)
	NewLev := getChessLv(ChessMinLv, ChessMaxLv, Diff)
	NewLev1 := mergeDataCfg.DynamicLev(NewLev, EmitChessId, Color)
	MaxLev := mergeDataCfg.GetMaxLvByColor(Color)
	NewLev1 = min(NewLev1, MaxLev)
	ChessId := mergeDataCfg.GetChessIdByLvAndColor(NewLev1, Color)
	ProductColor := mergeDataCfg.GetEmitProduceType(EmitChessId)
	for _, i := range ProductColor {
		if i == Color {
			continue
		}
		NewLev2 := mergeDataCfg.DynamicLev2(NewLev1, EmitChessId, Color, i)
		NewLev2 = adjustLev(NewLev2, EnergyMul)
		MaxLev := mergeDataCfg.GetMaxLvByColor(i)
		NewLev2 = min(NewLev2, MaxLev)
		ChessId2 := mergeDataCfg.GetChessIdByLvAndColor(NewLev2, i)
		if ChessId2 != 0 {
			o.ChessPool = append(o.ChessPool, ChessId2)
		}
	}
	o.ChessPool = GoUtil.ShuffleArray(o.ChessPool)
	if len(o.ChessPool) > 200 {
		o.ChessPool = o.ChessPool[:200]
	}
	return ChessId
}

// 初始化棋子难度映射表
func initReflectChess(Emits []int, EnergyMul int) {
	reflectChess = make(map[int]int)
	Start, End := 0, 0
	for _, Emit := range Emits {
		ProduceColor := mergeDataCfg.GetEmitProduceType(Emit)
		if len(ProduceColor) == 0 || ProduceColor[0] == "" {
			continue
		}
		ChessMinLv, ChessMaxLv := getChesslvRange(Emit, EnergyMul)
		Product := mergeDataCfg.GetEmitProduceChessType(Emit)
		Start = ChessMinLv
		End = ChessMinLv + (ChessMaxLv-ChessMinLv+1)/3 - 1
		for _, v := range Product {
			Adjust := mergeDataCfg.DynamicAdjust(Emit, v)
			initReflectChess2(v, Start, End, DIFF_LOW, Adjust)
		}
		Start = ChessMinLv + (ChessMaxLv-ChessMinLv+1)/3
		End = ChessMinLv + (ChessMaxLv-ChessMinLv+1)/3*2 - 1
		for _, v := range Product {
			Adjust := mergeDataCfg.DynamicAdjust(Emit, v)
			initReflectChess2(v, Start, End, DIFF_MID, Adjust)
		}
		Start = ChessMinLv + (ChessMaxLv-ChessMinLv+1)/3*2
		End = ChessMaxLv
		for _, v := range Product {
			Adjust := mergeDataCfg.DynamicAdjust(Emit, v)
			initReflectChess2(v, Start, End, DIFF_HIGH, Adjust)
		}
	}
}

func initReflectChess2(Color string, Start, End, Diff, adjust int) {
	for i := Start; i <= End; i++ {
		Lv := max(i-adjust, 1)
		ChessId := mergeDataCfg.GetChessIdByLvAndColor(Lv, Color)
		reflectChess[ChessId] = Diff
	}
}

// 调整棋子等级
func adjustLev(Lev, EnergyMul int) int {
	return max(min(Lev, EnergyMul+12), EnergyMul+1)
}

// 获取发射器系列
func getEmitBySeries(EmitList []int, EmitId string) int {
	for _, v := range EmitList {
		ProduceColor := mergeDataCfg.GetEmitProduceType(v)
		if len(ProduceColor) == 0 || ProduceColor[0] == "" {
			continue
		}
		if mergeDataCfg.GetEmitId(v) == EmitId {
			return v
		}
	}
	return 0
}
