package order

import (
	"fmt"
	"server/GoUtil"
	startOrderCfg "server/conf/StartOrder"
	limitedTimeEventCfg "server/conf/limitedTimeEvent"
	mergeDataCfg "server/conf/mergeData"
	orderCfg "server/conf/order"
	playroomCfg "server/conf/playroom"
	"server/game/mod/item"
	"server/msg"
	"sort"
	"time"
)

type OrderMod struct {
	OrderList       map[int]Order // 订单列表
	Auto_id         int           // 订单自增id
	Step            int           // 当前订单步骤
	LastDiff        int           // 上一个订单难度
	LastOrder       Order         // 上一个订单
	LastNormalOrder Order         // 上一个普通订单
	EimtOrder       map[string]struct{}
	PreheatStep     map[string]int // 预热订单步骤
	EmitShuffle     []string       // 发射器乱序
	ChessPool       []int          // 棋子池
}

type Order struct {
	MergeId   []int // 合成id
	Diff      int   // 难度
	Type      int   // 类型
	Timestamp int64 // 时间戳
}

const (
	Common_type      = 1 // 普通订单
	Extra_type       = 2 // 额外订单
	Super_type       = 3 // 超级订单
	Preheat_type     = 4 // 预热订单
	Trigger_type     = 5 // 触发订单
	Clean_type       = 6 // 退役发射器清理订单
	Clean_Order_type = 7 // 清理无法生成订单的棋子
	Clean_type2      = 8 // 棋盘空格不足清理棋子的订单
	COMFORT_TYPE     = 9 // 安慰订单

	DIFF_LOW  = 1 // 低难度
	DIFF_MID  = 2 // 中难度
	DIFF_HIGH = 3 // 高难度
)

func (o *OrderMod) InitData() {
	if o.EimtOrder == nil {
		o.EimtOrder = make(map[string]struct{})
	}
	if o.PreheatStep == nil {
		o.PreheatStep = make(map[string]int)
	}
	if o.Step == 0 {
		o.OrderList = make(map[int]Order)
		Cfg := startOrderCfg.GetStartOrderByStep(o.Step + 1)
		o.Step = 1
		o.Auto_id = 0
		o.LastDiff = DIFF_LOW
		for _, v := range Cfg {
			o.Auto_id++
			o.OrderList[o.Auto_id] = Order{
				Type:    Common_type,
				MergeId: v.MergeList,
			}
		}
	}
	for k, v := range o.OrderList {
		if GoUtil.InArray(0, v.MergeId) {
			delete(o.OrderList, k)
		}
	}
}

func (o *OrderMod) GetOrderList() map[int]Order {
	return o.OrderList
}

// 领取奖励
func (o *OrderMod) RewardOrder(id int) ([]*item.Item, []int, int, int, error) {
	ItemList := make([]*item.Item, 0)
	MergeList := make([]int, 0)
	if v, ok := o.OrderList[id]; ok {
		o.LastOrder = v
		delete(o.OrderList, id)
		Star := 0
		for _, v := range v.MergeId {
			Star += mergeDataCfg.GetStarById(v)
		}
		if v.Type == Super_type {
			Items := limitedTimeEventCfg.GetSuperOrderReward(Star)
			ItemList = append(ItemList, Items...)
		} else {
			ItemList = append(ItemList, &item.Item{Id: item.ITEM_STAR_ID, Num: Star})
		}
		return ItemList, v.MergeId, v.Type, Star, nil
	}
	return ItemList, MergeList, 0, 0, fmt.Errorf("订单不存在, 订单id%d", id)
}

// 生成新订单
func (o *OrderMod) CreateOrder(lv int, Emit []int, EnergyMul int) error {
	if len(Emit) == 0 {
		return nil
	}
	switch o.LastOrder.Type {
	case Preheat_type:
		ChessId := o.LastOrder.MergeId[0]
		ChessColor := mergeDataCfg.GetColorById(ChessId)
		PreheatStep := o.PreheatStep[ChessColor]
		if PreheatStep < 4 {
			NewChessId := mergeDataCfg.GetChessIdByLvAndColor(EnergyMul+PreheatStep+1, ChessColor)
			if NewChessId == 0 {
				return fmt.Errorf("CreateOrder: NewChessId is 0, EnergyMul: %d, PreheatStep: %d, ChessColor: %s", EnergyMul, PreheatStep, ChessColor)
			}
			o.addOrder([]int{NewChessId}, DIFF_LOW, Preheat_type)
			o.PreheatStep[ChessColor]++
		}
	default:
		if o.Step < 12 {
			n := 0
			for _, v := range o.OrderList {
				if v.Type == Common_type {
					n++
				}
			}
			if n != 0 {
				return nil
			}
			Cfg := startOrderCfg.GetStartOrderByStep(o.Step + 1)
			o.Step++
			for _, v := range Cfg {
				o.addOrder(v.MergeList, DIFF_LOW, Common_type)
			}
			return nil
		} else {
			/// 生成优先订单
			if o.CreatePriorityOrder(lv, Emit) {
				return nil
			}
			MaxOrderNum := orderCfg.GetOrderNum(lv)
			n := 0
			for _, v := range o.OrderList {
				if v.Type == Common_type || v.Type == Clean_type {
					n++
				}
			}
			for i := n; i < MaxOrderNum; i++ {
				err := o.CreateNormalOrder(lv, Emit, EnergyMul)
				if err != nil {
					return err
				}
			}
		}
	}
	return nil
}

func (o *OrderMod) CreatePriorityOrder(lv int, Emit []int) bool {
	if len(Emit) == 0 {
		return false
	}
	ChessList := make(map[string]int)
	for _, v := range o.OrderList {
		for _, vv := range v.MergeId {
			Color := mergeDataCfg.GetColorById(vv)
			if vvv, ok := ChessList[Color]; ok {
				OldLv := mergeDataCfg.GetLvById(vvv)
				NewLv := mergeDataCfg.GetLvById(vv)
				if NewLv > OldLv {
					ChessList[Color] = vv
				}
			} else {
				ChessList[Color] = vv
			}
		}
	}
	for v := range Emit {
		Produce := mergeDataCfg.GetEmitProduceChessType(v)
		if len(Produce) < 2 {
			continue
		}
		for k, v := range ChessList {
			if k == Produce[0] {
				MaxLv := mergeDataCfg.GetMaxLvById(v)
				DurLv := int((MaxLv - 3) * 1 / 3)
				ChessLv := mergeDataCfg.GetLvById(v)
				if ChessLv > (3 + DurLv*2) {
					B := GoUtil.RandMap(map[int]int{0: 80, 1: 20})
					if B == 1 {
						NewColor := GoUtil.RandStringSlice(Produce[1:])
						DiffLv := GoUtil.RandMap(map[int]int{DIFF_LOW: 70, DIFF_MID: 30})
						NewChessId := 0
						switch DiffLv {
						case DIFF_LOW:
							NewLv := GoUtil.RandNum(4, 3+DurLv)
							NewChessId = mergeDataCfg.GetChessIdByLvAndColor(NewLv, NewColor)
						case DIFF_MID:
							NewLv := GoUtil.RandNum(4+DurLv, 3+DurLv*2)
							NewChessId = mergeDataCfg.GetChessIdByLvAndColor(NewLv, NewColor)
						}
						o.addOrder([]int{NewChessId}, DiffLv, Common_type)
						return true
					}
				}
			}
		}
	}
	return false
}

// 生成新订单
func (o *OrderMod) CreateNormalOrder(lv int, Emit []int, EnergyMul int) error {
	if len(Emit) == 0 {
		return nil
	}
	randNum := 0
	mergeList := make([]int, 0)
	OrderDiff := DIFF_LOW
	var err error
	for {
		if randNum > 50 {
			break
		}
		randNum++
		mergeList, OrderDiff, err = randOrderChess(o, lv, Emit, EnergyMul)
		if err != nil {
			continue
		}
		lastMergelist := o.LastNormalOrder.MergeId
		conbine := false
		for _, v := range mergeList {
			if GoUtil.InArray(v, lastMergelist) {
				conbine = true
				break
			}
		}
		if conbine {
			continue
		}
		break
	}
	// log.Printf("CreateNormalOrder: %v, %v, %v", mergeList, OrderDiff, err)
	o.addOrder(mergeList, OrderDiff, Common_type)
	return nil
}

// 生成超级订单
func (o *OrderMod) CreateSuperOrder(lv int, Emit []int, EnergyMul int) error {
	if len(Emit) == 0 {
		return nil
	}
	randNum := 0
	mergeList := make([]int, 0)
	OrderDiff := DIFF_LOW
	var err error
	for {
		if randNum > 50 {
			break
		}
		randNum++
		mergeList, OrderDiff, err = randSuperOrderChess(o, lv, Emit, EnergyMul)
		if err != nil {
			continue
		}
		lastMergelist := o.LastNormalOrder.MergeId
		conbine := false
		for _, v := range mergeList {
			if GoUtil.InArray(v, lastMergelist) {
				conbine = true
				break
			}
		}
		if conbine {
			continue
		}
		break
	}
	o.addOrder(mergeList, OrderDiff, Super_type)
	return nil
}

/*
*
触发订单生成规则：
1.有触发订单时，不重复生成
2.检索当前已有的订单中，除特殊订单外星星基础收益数值(订单收益数低于1000)最高的订单
*/
func (o *OrderMod) CreateTriggerOrder(lv int, Emit []int, EnergyMul int) (int, error) {
	if lv < playroomCfg.GetUnLockLv() {
		return 0, nil
	}
	StarCfg := playroomCfg.GetOrderStar()
	type info struct {
		k int
		v Order
	}
	orderList := make([]info, 0)
	// 查找奖励小于1000的订单， 取最大的订单
	for k, v := range o.OrderList {
		if v.Type == Trigger_type {
			return 0, nil
		}
		if v.Type != Common_type {
			continue
		}
		Star := getOrderStar(v.MergeId)
		if Star > StarCfg {
			continue
		}
		orderList = append(orderList, info{k, v})
	}
	sort.Slice(orderList, func(i, j int) bool {
		return getOrderStar(orderList[i].v.MergeId) > getOrderStar(orderList[j].v.MergeId)
	})
	// 没有奖励小于1000的订单且无法生成，去最小的订单
	if len(orderList) == 0 && EnergyMul >= 8 {
		for k, v := range o.OrderList {
			if v.Type != Common_type {
				continue
			}
			orderList = append(orderList, info{k, v})
		}
		sort.Slice(orderList, func(i, j int) bool {
			return getOrderStar(orderList[i].v.MergeId) < getOrderStar(orderList[j].v.MergeId)
		})
	}
	if len(orderList) != 0 {
		o.OrderList[orderList[0].k] = Order{
			MergeId:   orderList[0].v.MergeId,
			Diff:      orderList[0].v.Diff,
			Type:      Trigger_type,
			Timestamp: time.Now().Unix(),
		}
		return getOrderStar(orderList[0].v.MergeId), nil
	}

	// 随机生成新的订单
	if len(Emit) == 0 {
		return 0, nil
	}
	randNum := 0
	mergeList := make([]int, 0)
	for {
		if randNum > 50 {
			break
		}
		randNum++
		mergeList1, _, err := randOrderChess(o, lv, Emit, EnergyMul)
		if err != nil {
			continue
		}

		if getOrderStar(mergeList1) < StarCfg {
			mergeList = mergeList1
			break
		}
	}
	if len(mergeList) > 0 {
		o.addOrder(mergeList, DIFF_LOW, Trigger_type)
		return getOrderStar(mergeList), nil
	} else {
		for k, v := range o.OrderList {
			if v.Type != Common_type {
				continue
			}
			orderList = append(orderList, info{k, v})
		}
		sort.Slice(orderList, func(i, j int) bool {
			return getOrderStar(orderList[i].v.MergeId) < getOrderStar(orderList[j].v.MergeId)
		})
		o.OrderList[orderList[0].k] = Order{
			MergeId:   orderList[0].v.MergeId,
			Diff:      orderList[0].v.Diff,
			Type:      Trigger_type,
			Timestamp: time.Now().Unix(),
		}
		return getOrderStar(orderList[0].v.MergeId), nil
	}
}

func (o *OrderMod) addOrder(ChessList []int, Diff int, Type int) {
	o.Auto_id++
	Order := Order{
		MergeId:   ChessList,
		Diff:      Diff,
		Type:      Type,
		Timestamp: time.Now().Unix(),
	}
	o.OrderList[o.Auto_id] = Order
	if Type == Common_type {
		o.LastNormalOrder = Order
	}
	o.LastDiff = Diff
}

func (o *OrderMod) CreateCleanOrder(ChessList []int) bool {
	o.addOrder(ChessList, DIFF_LOW, Clean_type)
	return true
}

func (o *OrderMod) CreateCleanOrder2(ChessList []int) bool {
	o.addOrder(ChessList, DIFF_LOW, Clean_Order_type)
	return true
}

func (o *OrderMod) CreateExtraOrder(AddChess, AddNewEmit, ChessList []int, EnergyMul int) bool {
	GetExtraEmitId := mergeDataCfg.GetExtraEmitId()
	b1 := false
	OrderEmit := 0
	MaxLvChess := make(map[int]int)
	for _, v := range AddNewEmit {
		Emit_Id := mergeDataCfg.GetEmitId(v)
		_, ok := GetExtraEmitId[Emit_Id]
		_, ok1 := o.EimtOrder[Emit_Id]
		ChessColor := mergeDataCfg.GetEmitProduceChessType(v)
		if ok && !ok1 && len(ChessColor) > 0 {
			b1 = true
			OrderEmit = v
			o.EimtOrder[Emit_Id] = struct{}{}
			break
		}
	}
	for _, ChessId := range AddChess {
		Lv := mergeDataCfg.GetLvById(ChessId)
		Type := mergeDataCfg.GetTypeById(ChessId)
		if Type != "Product" {
			continue
		}
		MaxLv := mergeDataCfg.GetMaxLvById(ChessId)
		if Lv == MaxLv {
			MaxLvChess[ChessId]++
		}
	}
	//额外订单补充1；CDEG发射器首次合成时，生成其对应2及棋子订单，完成后生成3及，再完成生成4及的；
	if b1 {
		ChessColor := mergeDataCfg.GetEmitProduceChessType(OrderEmit)
		ChessId := mergeDataCfg.GetChessIdByLvAndColor(EnergyMul+1, ChessColor[0])
		if ChessId != 0 {
			o.PreheatStep[ChessColor[0]] = 1
			o.addOrder([]int{ChessId}, DIFF_LOW, Preheat_type)
		}
	}
	//额外订单补充2；当玩家的棋盘中出现三个相同的满级产物时，立刻生成一个对应的收购订单；
	for k := range MaxLvChess {
		ChessNum := GoUtil.GetElemNum(ChessList, k)
		OrderChess := 0
		for _, order := range o.OrderList {
			for _, v := range order.MergeId {
				if v == k {
					OrderChess++
				}
			}
		}
		OrderNum := (ChessNum - OrderChess) / 3
		for i := 0; i < OrderNum; i++ {
			b1 = true
			o.addOrder([]int{k, k, k}, DIFF_LOW, Extra_type)
		}
	}
	return b1
}

// 返回订单列表
func (o *OrderMod) BackData() *msg.ResOrderList {
	OrderList := make([]*msg.Order, 0)
	for k, v := range o.OrderList {
		mergeList := GoUtil.IntToInt32(v.MergeId)
		Order := &msg.Order{
			Id:      int32(k),
			ChessId: mergeList,
			Type:    int32(v.Type),
		}
		OrderList = append(OrderList, Order)
	}
	return &msg.ResOrderList{
		OrderList: OrderList,
	}
}

func (o *OrderMod) RemoveSuperOrder() {
	for k, v := range o.OrderList {
		if v.Type == Super_type {
			delete(o.OrderList, k)
		}
	}
}

func (o *OrderMod) CheckSuperOrder() bool {
	for _, v := range o.OrderList {
		if v.Type == Super_type {
			return true
		}
	}
	return false
}

/*
* 根据能量倍数 调整订单
 */
func (o *OrderMod) ChangeEnergyMul(lv int, Emit []int, EnergyMul int, ChessList []int) {
	for k, v := range o.OrderList {
		NeedTrigger := false
		HasOne := false
		for _, vv := range v.MergeId {
			Lv := mergeDataCfg.GetLvById(vv)
			if GoUtil.InArray(vv, ChessList) {
				HasOne = true
				break
			}
			if Lv >= EnergyMul+1 && Lv <= EnergyMul+12 {
				continue
			}
			NeedTrigger = true
		}
		if HasOne { // 棋盘上有订单中的棋子，不进行修改
			continue
		}
		if v.Type == Preheat_type { // 预热订单 修改倍数时修改棋子等级
			ChessId := v.MergeId[0]
			ChessColor := mergeDataCfg.GetColorById(ChessId)
			PreheatStep := o.PreheatStep[ChessColor]
			NewChessId := mergeDataCfg.GetChessIdByLvAndColor(EnergyMul+PreheatStep, ChessColor)
			if NewChessId == 0 {
				continue
			}
			delete(o.OrderList, k)
			o.addOrder([]int{NewChessId}, DIFF_LOW, Preheat_type)
		}
		if v.Type != Common_type {
			continue
		}
		/**
		当每次倍数调整（玩家主动调整或因为体力不足跌落）时，在普通订单中（即不包括偷猫订单、超级订单），如果出现超出上下阈值：
		订单棋子等级<n且该棋子棋盘上没有
		订单棋子等级>n+11 且该棋子在棋盘上没有
		则删除该订单，重新生成一个普通订单
		*/
		if NeedTrigger {
			delete(o.OrderList, k)
			o.CreateNormalOrder(lv, Emit, EnergyMul)
		}
	}
}

func (o *OrderMod) Retire(EmitId string) {
	ChessPool := make([]int, 0)
	Product := mergeDataCfg.GetEmitProduce(EmitId)
	for _, v := range o.ChessPool {
		Color := mergeDataCfg.GetColorById(v)
		if GoUtil.InStringArray(Color, Product) {
			continue
		}
		ChessPool = append(ChessPool, v)
	}
	o.ChessPool = ChessPool
	o.EmitShuffle = nil
}

func (o *OrderMod) DelOrder(OrderId int) error {
	Order, ok := o.OrderList[OrderId]
	if !ok {
		return fmt.Errorf("order not exist")
	}
	if Order.Type != Clean_Order_type {
		return fmt.Errorf("order type wrong")
	}
	delete(o.OrderList, OrderId)
	return nil
}

func (o *OrderMod) CreateComfortOrder(lv int, Emit []int, EnergyMul, Diff, ChessNum int) error {
	if len(Emit) == 0 {
		return nil
	}
	randNum := 0
	mergeList := make([]int, 0)
	var err error
	for {
		if randNum > 50 {
			break
		}
		randNum++
		mergeList, _, err = randOrderChessWithDiff(o, lv, Emit, EnergyMul, Diff, ChessNum)
		if err != nil {
			continue
		}

		break
	}
	o.addOrder(mergeList, Diff, COMFORT_TYPE)
	return nil
}
