package order

import (
	"fmt"
	mergeDataCfg "server/conf/merge_data"
	orderCfg "server/conf/order"
	"server/game/mod/item"
	GoUtil "server/game_util"
	"server/msg"
	"strings"
	"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         // 发射器乱序
	ColorShuffle    []string         // 棋子系列乱序
	LastColor       string           // 上次生成订单的棋子系列
	ChessPool       []int            // 棋子池
	ChessPool2      map[string][]int // 按系列分类的棋子池
	OrderPool       map[int]*Order   // 订单池
	FinishOrder     []int            // 已完成订单
	IsCharge        bool             // 是否充值
	AutoEmit        []string         // 自动发射器
	LastChess       int              // 上次生成订单的棋子
	NextDiff        int              // 下次订单难度
	ComfortEndTime  int
}

type Order struct {
	MergeId   []int // 合成id
	Diff      int   // 难度
	Type      int   // 类型
	Timestamp int64 // 时间戳
	Q         int
	S         int
	Items     []*item.Item // 奖励物品
}

var PreheatItems = map[int][]*item.Item{
	1: {item.NewItem(item.ITEM_ENERGY_GIFT_ID, 1)},
	2: {item.NewItem(item.ITEM_DIAMOND_LV2_ID, 1)},
	3: {item.NewItem(item.ITEM_LAUNCHER_LOW_ID, 1)},
}

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  // 安慰订单
	Guide_type       = 10 // 引导订单
	Pet_type         = 11 // 宠物订单
	Preview_type     = 12 // 预览订单
	Fixed_type       = 13 // 固定订单
	Playroom_type    = 14 // playroom装饰物订单
	Part_type        = 15 // 零件订单

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

	TRIGGER_TYPE_ORDER = "Order" // 订单触发器
	TRIGGER_TYPE_LV    = "Lv"    // 等级触发器
)

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.OrderPool == nil {
		o.OrderPool = make(map[int]*Order)
	}
	if len(o.OrderList) == 0 {
		o.OrderList = make(map[int]Order)
		o.TriggerOrder(1, TRIGGER_TYPE_ORDER, nil, 1)
	}
	for k, v := range o.OrderList {
		if GoUtil.InArray(0, v.MergeId) || len(v.MergeId) == 0 {
			delete(o.OrderList, k)
		}
	}
	if o.ChessPool2 == nil {
		o.ChessPool2 = make(map[string][]int)
	}
	if o.Auto_id == 0 {
		o.Auto_id = 10000
	}
}

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)
		}
		ItemList = v.Items
		if v.Type == Guide_type {
			return nil, v.MergeId, v.Type, 0, nil
		}
		if v.Type == Fixed_type || v.Type == Playroom_type {
			o.FinishOrder = append(o.FinishOrder, id)
		}
		if GoUtil.InArray(78, o.FinishOrder) {
			o.AutoEmit, _ = GoUtil.PopStringElemSlice(o.AutoEmit, "D")
		}
		if GoUtil.InArray(79, o.FinishOrder) {
			o.AutoEmit, _ = GoUtil.PopStringElemSlice(o.AutoEmit, "I")
		}
		return ItemList, v.MergeId, v.Type, Star, nil
	}
	return ItemList, MergeList, 0, 0, fmt.Errorf("订单不存在, 订单id%d", id)
}
func (o *OrderMod) CreateOrderSeed(Order *Order) error {
	for k, v := range o.OrderPool {
		if v.Timestamp == Order.Timestamp {
			delete(o.OrderPool, k)
			break
		}
	}
	o.addOrder(Order.MergeId, DIFF_LOW, Common_type)
	return nil
}

func (o *OrderMod) CreatOrderPool(lv int, Emit []int, EnergyMul int) error {
	o.OrderPool = make(map[int]*Order)
	index := 1
	for i := 0; i < 10; i++ {
		ChessList := o.CreateNormalOrderSeed(lv, Emit, EnergyMul, DIFF_LOW)
		if len(ChessList) == 0 {
			continue
		}
		o.OrderPool[index] = &Order{
			MergeId:   ChessList,
			Diff:      DIFF_LOW,
			Timestamp: int64(index),
		}
		index++
	}
	for i := 0; i < 10; i++ {
		ChessList := o.CreateNormalOrderSeed(lv, Emit, EnergyMul, DIFF_MID)
		if len(ChessList) == 0 {
			continue
		}
		o.OrderPool[index] = &Order{
			MergeId:   ChessList,
			Diff:      DIFF_LOW,
			Timestamp: int64(index),
		}
		index++
	}
	for i := 0; i < 10; i++ {
		ChessList := o.CreateNormalOrderSeed(lv, Emit, EnergyMul, DIFF_HIGH)
		if len(ChessList) == 0 {
			continue
		}
		o.OrderPool[index] = &Order{
			MergeId:   ChessList,
			Diff:      DIFF_LOW,
			Timestamp: int64(index),
		}
		index++
	}
	return nil
}

// 触发生成新的固定订单
func (o *OrderMod) TriggerOrder(lv int, Type string, Emit []int, EnergyMul int) error {
	TriggerOrderList := orderCfg.GetStartOrderList()
	FixedOrder := 0
	for _, v := range o.OrderList {
		if v.Type == Fixed_type {
			FixedOrder++
		}
	}
	OrderList := make(map[int]Order, len(o.OrderList))
	for k, v := range o.OrderList {
		OrderList[k] = v
	}
	// 触发生成新的固定订单
	for _, v := range TriggerOrderList {
		if GoUtil.InArray(v.Id, o.FinishOrder) {
			continue
		}
		orderInfo, exists := OrderList[v.Id]
		if exists && v.Preview == "" {
			continue
		}
		// 预览条件不为空且未存在且未完成
		if v.Preview != "" && !exists && !GoUtil.InArray(v.Id, o.FinishOrder) {
			if o.CheckCondition(lv, v.Preview, Type, Emit, FixedOrder, OrderList) {
				o.addFixOrder(v.Id, v.MergeList, Preview_type, v.Items)
			}
		}
		if v.Appear != "" {
			if o.CheckCondition(lv, v.Appear, Type, Emit, FixedOrder, OrderList) {
				Type := Fixed_type
				OrderType := orderCfg.GetOrderType(v.Id)
				if OrderType != 0 {
					Type = OrderType
				}
				if exists {
					orderInfo.Type = Fixed_type
					o.OrderList[v.Id] = orderInfo
				} else {
					o.addFixOrder(v.Id, v.MergeList, Type, v.Items)
					if v.Id == 78 {
						o.Retire("D")
						o.AutoEmit = append(o.AutoEmit, "D")
					}
					if v.Id == 79 {
						o.Retire("I")
						o.AutoEmit = append(o.AutoEmit, "I")
					}
				}
			}
		}
	}
	return nil
}

func (o *OrderMod) CheckCondition(lv int, condition, Type string, Emit []int, FixedOrder int, OrderList map[int]Order) bool {
	r1 := strings.Split(condition, "|")
	for _, v := range r1 {
		r2 := strings.Split(v, "=")
		switch r2[0] {
		case "Finish":
			id := GoUtil.Int(r2[1])
			if !GoUtil.InArray(id, o.FinishOrder) && id != 0 {
				return false
			}
			if id == 0 && Type != TRIGGER_TYPE_ORDER {
				return false
			}
		case "Lv":
			id := GoUtil.Int(r2[1])
			if lv < id {
				return false
			}
		case "OrderNum":
			id := GoUtil.Int(r2[1])
			if FixedOrder != id {
				return false
			}
		case "Order":
			id := GoUtil.Int(r2[1])
			_, ok := OrderList[id]
			if !GoUtil.InArray(id, o.FinishOrder) && !ok {
				return false
			}
		case "Emit":
			Class := []string{}
			for _, v := range Emit {
				Class = append(Class, mergeDataCfg.GetEmitId(v))
			}
			if !GoUtil.InStringArray(r2[1], Class) {
				return false
			}
		case "EmitMax":
			Class := []string{}
			for _, v := range Emit {
				EmitLv := mergeDataCfg.GetLvById(v)
				MaxLv := mergeDataCfg.GetMaxLvById(v)
				if EmitLv < MaxLv {
					continue
				}
				Class = append(Class, mergeDataCfg.GetEmitId(v))
			}
			if !GoUtil.InStringArray(r2[1], Class) {
				return false
			}
		}
	}
	return true
}

// 生成新订单
func (o *OrderMod) CreateOrder(lv int, Emit []int, EnergyMul, OrderType int) error {
	if len(Emit) == 0 {
		return nil
	}
	/// 生成优先订单
	if o.CreatePriorityOrder(lv, Emit) {
		return nil
	}
	err := o.CreateNormalOrder(lv, Emit, EnergyMul, OrderType)
	return err
}

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)
						}
						if NewChessId == 0 {
							continue
						}
						o.addOrder([]int{NewChessId}, DiffLv, Common_type)
						return true
					}
				}
			}
		}
	}
	return false
}

// 生成新订单
func (o *OrderMod) CreateNormalOrderSeed(lv int, Emit []int, EnergyMul int, Diff int) []int {
	if len(Emit) == 0 {
		return nil
	}
	randNum := 0
	mergeList := make([]int, 0)
	var err error
	for {
		if randNum > 50 {
			break
		}
		randNum++
		mergeList, _, err = randOrderChessSeed(o, Emit, EnergyMul, Diff)
		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
	}
	return mergeList
}

// 生成新订单
func (o *OrderMod) CreateNormalOrder(lv int, Emit []int, EnergyMul, OrderType 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, OrderType)
		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
	}
	for _, v := range mergeList {
		if v == 0 {
			return nil
		}
	}
	o.addOrder(mergeList, OrderDiff, OrderType)
	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)
	// 忽视上一个订单的难度，生成此订单时，难度默认为50%概率的中难度、50%概率的高难度
	OrderDiff := DIFF_MID
	if GoUtil.RandNum(1, 100) <= 50 {
		OrderDiff = DIFF_HIGH
	}
	var err error
	for {
		if randNum > 50 {
			break
		}
		randNum++
		mergeList, OrderDiff, err = randSuperOrderChess(o, lv, Emit, EnergyMul, OrderDiff)
		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
}
func (o *OrderMod) addOrder(ChessList []int, Diff int, Type int) int {
	o.Auto_id++
	Order := Order{
		MergeId:   ChessList,
		Diff:      Diff,
		Type:      Type,
		Timestamp: time.Now().Unix(),
		Items:     nil,
	}
	o.OrderList[o.Auto_id] = Order
	if Type == Common_type {
		o.LastNormalOrder = Order
	}
	o.LastDiff = Diff
	return o.Auto_id
}
func (o *OrderMod) AddExtraOrder(ChessList []int) {
	o.addOrder(ChessList, DIFF_LOW, Extra_type)
}
func (o *OrderMod) AddFixOrder(Id int, ChessList []int, Type int, Items []*item.Item) {
	o.addFixOrder(Id, ChessList, Type, Items)
}
func (o *OrderMod) addFixOrder(Id int, ChessList []int, Type int, Items []*item.Item) {
	Order := Order{
		MergeId:   ChessList,
		Type:      Type,
		Timestamp: time.Now().Unix(),
		Items:     Items,
	}
	o.OrderList[Id] = Order
}
func (o *OrderMod) AddPreheatOrder(ChessList []int, Diff int, Type int, Items []*item.Item) int {
	return o.addPreheatOrder(ChessList, Diff, Type, Items)
}
func (o *OrderMod) addPreheatOrder(ChessList []int, Diff int, Type int, Items []*item.Item) int {
	o.Auto_id++
	Order := Order{
		MergeId:   ChessList,
		Diff:      Diff,
		Type:      Type,
		Timestamp: time.Now().Unix(),
		Items:     Items,
	}
	o.OrderList[o.Auto_id] = Order
	return o.Auto_id
}

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, Level int) bool {
	BeginExtraEmitId := orderCfg.GetEmitExtraOrder() // 从发射器F系列开始
	b1 := false
	OrderEmit := 0
	MaxLvChess := make(map[int]int)
	for _, v := range AddNewEmit {
		Emit_Id := mergeDataCfg.GetEmitId(v)
		ok := Emit_Id >= BeginExtraEmitId
		_, 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]++
		}
	}
	b3 := false
	//额外订单补充2；当玩家的棋盘中出现三个相同的满级产物时，立刻生成一个对应的收购订单；
	for k := range MaxLvChess {
		ChessNum := GoUtil.GetElemNum(ChessList, k)
		if ChessNum >= 3 && Level >= 12 {
			b2 := true
			for _, v := range o.OrderList {
				if GoUtil.SliceEqual(v.MergeId, []int{k, k, k}) {
					b2 = false
					break
				}
			}
			if b2 {
				b3 = true
				o.addOrder([]int{k, k, k}, DIFF_LOW, Extra_type)
			}
		}
	}
	//额外订单补充1；CDEG发射器首次合成时，生成其对应2及棋子订单，完成后生成3及，再完成生成4及的；
	if b1 {
		ChessColor := mergeDataCfg.GetEmitProduceChessType(OrderEmit)
		if len(ChessColor) == 0 {
			return b1
		}
		ChessId := mergeDataCfg.GetChessIdByLvAndColor(EnergyMul+1, ChessColor[0])
		if ChessId != 0 {
			o.PreheatStep[ChessColor[0]] = 1
			Items := PreheatItems[1]
			o.addPreheatOrder([]int{ChessId}, DIFF_LOW, Preheat_type, Items)
		}
	}
	return b1 || b3
}

// 返回订单列表
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),
			Items:   item.ItemToMsg(v.Items),
		}
		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 {
		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)
			Items, ok := PreheatItems[PreheatStep]
			if !ok {
				Items = []*item.Item{item.NewItem(item.ITEM_STAR_ID, GetOrderStar([]int{NewChessId}, Emit))}
			}
			o.addPreheatOrder([]int{NewChessId}, DIFF_LOW, Preheat_type, Items)
		}
	}

	MaxStep := orderCfg.GetMaxStep()
	if o.Step < MaxStep { // 还在新手引导阶段
		return
	}
	for k, v := range o.OrderList {
		NeedTrigger := false
		for _, vv := range v.MergeId {
			Lv := mergeDataCfg.GetLvById(vv)
			Color := mergeDataCfg.GetColorById(vv)
			EmitId := GetEmitByColor(Emit, Color)
			_, Max := getChesslvRange(EmitId, EnergyMul, o.IsCharge)
			Adjust := mergeDataCfg.GetAdjust(EmitId, Color, EnergyMul)
			if Lv >= EnergyMul+1 && Lv <= Max-Adjust {
				continue
			}
			NeedTrigger = true
		}

		if v.Type != Common_type && v.Type != Pet_type {
			continue
		}
		/**
		当每次倍数调整（玩家主动调整或因为体力不足跌落）时，在普通订单中（即不包括偷猫订单、超级订单），如果出现超出上下阈值：
		订单棋子等级<n且该棋子棋盘上没有
		订单棋子等级>n+11 且该棋子在棋盘上没有
		则删除该订单，重新生成一个普通订单
		*/
		if NeedTrigger {
			delete(o.OrderList, k)
			o.CreateNormalOrder(lv, Emit, EnergyMul, v.Type)
		}
	}
}

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

func (o *OrderMod) DelOrder(OrderId int) (*Order, error) {
	Order, ok := o.OrderList[OrderId]
	if !ok {
		return nil, fmt.Errorf("order not exist")
	}
	if Order.Type != Clean_Order_type {
		return nil, fmt.Errorf("order type wrong")
	}
	delete(o.OrderList, OrderId)
	return &Order, 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, Emit, EnergyMul, Diff, ChessNum)
		if err != nil {
			continue
		}

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

func (o *OrderMod) ResetChessPool() {
	// o.ChessPool = make([]int, 0)
	// o.EmitShuffle = nil
}

func (o *OrderMod) SetIsCharge() {
	o.IsCharge = true
}

func (o *OrderMod) GetIsCharge() bool {
	return o.IsCharge
}
