package game

import (
	"fmt"
	mergeCluster "server/cluster"
	cardCfg "server/conf/card"
	catnipCfg "server/conf/catnip"
	decorateCfg "server/conf/decorate"
	itemCfg "server/conf/item"
	limitedTimeEventCfg "server/conf/limited_time_event"
	mailCfg "server/conf/mail"
	mergeDataCfg "server/conf/merge_data"
	orderCfg "server/conf/order"
	playroomCfg "server/conf/playroom"
	userCfg "server/conf/user"
	"server/game/mod/activity"
	"server/game/mod/card"
	"server/game/mod/decorate"
	"server/game/mod/friend"
	"server/game/mod/item"
	limitedTimeEvent "server/game/mod/limited_time_event"
	"server/game/mod/mail"
	"server/game/mod/msg"
	"server/game/mod/order"
	"server/game/mod/playroom"
	GoUtil "server/game_util"
	proto "server/msg"
	"server/pkg/github.com/name5566/leaf/log"
	"sort"
)

// 处理玩家异步请求
func (p *Player) HandleMsg(m *msg.Msg) {
	p.lock.Lock()        //加锁
	backup := p.BackUp() // 备份当前的 Player 值
	defer func() {
		if r := recover(); r != nil {
			log.Error("Handle msg uid : %d, msg : %v, fatal : %s", p.M_DwUin, m, r)
			p.Recover(backup) //还原Player的数据
		}
		p.lock.Unlock() //解锁
	}()
	p.args = make(map[string]interface{})
	err := p.handle(m)
	if err != nil {
		log.Debug("uid : %d, err : %s", p.M_DwUin, err)
		p.Recover(backup) //还原Player的数据
		return
	}

	// 处理在线消息
	if m.H == msg.MSG_TYPE_ONLINE {
		p.ProcessTrigger()
		p.SendClientRes()
	} else {
		p.Msg = nil
	}
}

// 消息处理
func (p *Player) handle(m *msg.Msg) error {
	switch m.Type {
	case msg.HANDLE_TYPE_APPLY: // 好友申请
		FriendMod := p.PlayMod.getFriendMod()
		ok := FriendMod.AddFriendApply(m.From)
		// 已申请
		if ok {
			return nil
		}
		p.AddLog(m.From, friend.LOG_TYPE_FRIEND_APPLY, "", m.SendT)
		PlayerSimpleData := G_GameLogicPtr.GetResSimplePlayerByUid(m.From)
		p.PushClientRes(&proto.ResFriendApplyNotify{
			Player: PlayerSimpleData,
			Type:   friend.FRIEND_NOTIFY_APPLY,
			Time:   int32(GoUtil.Now()),
		})
	case msg.HADNLE_TYPE_AGREE: // 同意好友申请
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.AgreeApply(m.From)
		PlayerSimpleData := G_GameLogicPtr.GetResSimplePlayerByUid(m.From)
		p.PushClientRes(&proto.ResFriendApplyNotify{
			Player: PlayerSimpleData,
			Type:   friend.FRIEND_NOTIFY_AGREE,
			Time:   int32(GoUtil.Now()),
		})
		// PlayroomMod := p.PlayMod.getPlayroomMod()
		// BaseMod := p.PlayMod.getBaseMod()
		// PlayroomMod.AddRoomPointAdd(BaseMod.GetLevel())
		// p.PlayroomBackData()
		p.TeLog("friend_add", map[string]interface{}{
			"player_id": m.From,
			"add_type":  "接受申请",
		})
		p.AddLog(m.From, friend.LOG_TYPE_FRIEND_BECOME, "", m.SendT)
	case msg.HANDLE_TYPE_DEL: // 删除好友
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.DelFriend(m.From)
		p.AddLog(m.From, friend.LOG_TYPE_FRIEND_APPLY, "", m.SendT)
		PlayerSimpleData := G_GameLogicPtr.GetResSimplePlayerByUid(m.From)
		p.PushClientRes(&proto.ResFriendApplyNotify{
			Player: PlayerSimpleData,
			Type:   friend.FRIEND_NOTIFY_DEL,
			Time:   int32(GoUtil.Now()),
		})
	case msg.HANDLE_TYPE_REFUSE: // 拒绝好友申请
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.RefuseApply(m.From)
		PlayerSimpleData := G_GameLogicPtr.GetResSimplePlayerByUid(m.From)
		p.PushClientRes(&proto.ResFriendApplyNotify{
			Player: PlayerSimpleData,
			Type:   friend.FRIEND_NOTIFY_REFUSE,
			Time:   int32(GoUtil.Now()),
		})
	case msg.HANDLE_TYPE_REQ_CARD: // 卡牌申请
		FriendMod := p.PlayMod.getFriendMod()
		CardInfo, ok := m.Extra.(card.CardInfo)
		if !ok {
			return nil
		}
		FriendMod.SetCardInfo(&CardInfo)
		p.PushClientRes(
			&proto.NotifyFriendCard{
				Info: GetCardInfoMsg(&CardInfo),
			},
		)
	case msg.HANDLE_TYPE_FACEBOOK_UNBIND: // facebook解绑
		FaceMod := p.PlayMod.getFaceMod()
		if FaceMod.SetId == 0 {
			FaceMod.SetId = 2
		}
	case msg.SERVER_ZERO_UPDATE:
		p.ZeroUpdate(nil)
	case msg.SERVER_NOON_UPDATE:
		p.NoonUpdate(nil)
	case msg.HANDLE_TYPE_INVITE_ADD_FRIEND: // 邀请添加好友
		FriendMod := p.PlayMod.getFriendMod()
		if m.From == 0 || m.From == int(p.M_DwUin) {
			return nil
		}
		FriendMod.AddFriend(m.From)
		p.TeLog("friend_add", map[string]interface{}{
			"player_id": m.From,
			"add_type":  "发起申请",
		})
		p.PlayMod.save()
	case msg.HANDLE_TYPE_INVITE_FRIEND: // 邀请好友
		InviteMod := p.PlayMod.getInviteMod()
		InviteMod.AddInvite(m.From)
		p.AddLog(m.From, friend.LOG_TYPE_FRIEND_INVITE, "", m.SendT)
		p.PlayMod.save()
		p.PushClientRes(InviteMod.NotifySuccess())
	case msg.HANDLE_TYPE_SEND_CARD: // B收到A赠送的卡牌
		CardInfo := m.Extra.(card.CardInfo)
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.SetCardInfo(&CardInfo)
		FriendMod.Interact(CardInfo.AUid, friend.INTERACT_TYPE_CARD, m.SendT)
		p.PushClientRes(
			&proto.NotifyFriendCard{
				Info: GetCardInfoMsg(&CardInfo),
			},
		)
		p.PlayMod.save()
	case msg.HANDLE_TYPE_EX_CARD_SELECT_TIMEOUT: // A收到B置换卡牌选择超时
		CardInfo := m.Extra.(card.CardInfo)
		CardMod := p.PlayMod.getCardMod()
		p.AddCard(CardInfo.CardId)
		CardMod.DelExCard(&CardInfo)
		p.PushClientRes(CardMod.NotifyCard())
		p.PushClientRes(CardMod.NotifyTimes())
	case msg.HANDLE_TYPE_EX_CARD_TIMEOUT: // B收到A同意置换卡牌超时
		CardInfo, ok := m.Extra.(card.CardInfo)
		if !ok {
			return nil
		}
		CardMod := p.PlayMod.getCardMod()
		p.AddCard(CardInfo.ExId)
		p.PushClientRes(CardMod.NotifyCard())
		p.PushClientRes(CardMod.NotifyTimes())
	case msg.HANDLE_TYPE_REG_CARD_FINISH, msg.HANDLE_TYPE_AGREE_CARD_FAIL: // B收到A的请求已结束
		CardInfo, ok := m.Extra.(card.CardInfo)
		if !ok {
			return nil
		}
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.DelCardInfo(CardInfo.Id)
		p.PushClientRes(
			&proto.NotifyFriendCard{
				Info: GetCardInfoMsg(&CardInfo),
			},
		)
		p.PlayMod.save()
	case msg.HANDLE_TYPE_AGREE_CARD: // A收到B同意卡牌
		CardInfo, ok := m.Extra.(card.CardInfo)
		if !ok {
			return nil
		}
		CardMod := p.PlayMod.getCardMod()
		OtherUid, err := CardMod.DelRequestCard(CardInfo.BUid)
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.SetCardInfo(&CardInfo)
		if err != nil { // 同意失败，请求已失效
			msg := &msg.Msg{Type: msg.HANDLE_TYPE_AGREE_CARD_FAIL, From: CardInfo.AUid, End: CardInfo.EndTime, Extra: CardInfo}
			FriendMgrSend(msg)
			return nil
		}
		for k, v := range OtherUid { // 通知好友请求已结束
			v.Status = card.STATUS_CARD_GIVE_3
			FriendMgrSend(&msg.Msg{Type: msg.HANDLE_TYPE_REG_CARD_FINISH, From: k, Extra: &v})
			CardMod.DelRequestCard(k)
		}
		p.PlayMod.save()
		p.PushClientRes(
			&proto.NotifyFriendCard{
				Info: GetCardInfoMsg(&CardInfo),
			},
		)
		p.PushClientRes(CardMod.NotifyTimes())
	case msg.HANDLE_TYPE_REG_CARD_REFUSE: // A收到B拒绝索要卡牌
		CardInfo, ok := m.Extra.(card.CardInfo)
		if !ok {
			return nil
		}
		CardMod := p.PlayMod.getCardMod()
		CardMod.DelRequestCard(CardInfo.BUid)
		CardMod.AddReqTimes(CardInfo.Id, CardInfo.StartTime)
		p.PlayMod.save()
		p.PushClientRes(CardMod.NotifyTimes())
		p.PushClientRes(CardMod.NotifyCard())
	case msg.HANDLE_TYPE_EX_CARD: // B收到A置换卡牌
		FriendMod := p.PlayMod.getFriendMod()
		CardInfo, ok := m.Extra.(card.CardInfo)
		if !ok {
			return nil
		}
		FriendMod.SetCardInfo(&CardInfo)
		FriendMod.Interact(CardInfo.AUid, friend.INTERACT_TYPE_EX, m.SendT)
		p.PlayMod.save()
		p.PushClientRes(
			&proto.NotifyFriendCard{
				Info: GetCardInfoMsg(&CardInfo),
			},
		)
	case msg.HANDLE_TYPE_SELECT_EX_CARD: // A收到B选择卡牌进行置换
		FriendMod := p.PlayMod.getFriendMod()
		CardInfo, ok := m.Extra.(card.CardInfo)
		if !ok {
			return nil
		}
		FriendMod.SetCardInfo(&CardInfo)
		p.PlayMod.save()
		p.PushClientRes(
			&proto.NotifyFriendCard{
				Info: GetCardInfoMsg(&CardInfo),
			},
		)
	case msg.HANDLE_TYPE_ARGREE_EX_CARD: // B收到A同意置换卡牌
		CardInfo, ok := m.Extra.(card.CardInfo)
		if !ok {
			return nil
		}
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.SetCardInfo(&CardInfo)
		p.PushClientRes(
			&proto.NotifyFriendCard{
				Info: GetCardInfoMsg(&CardInfo),
			},
		)
		p.PlayMod.save()
	case msg.HANDLE_TYPE_REFUSE_SELECT_CARD: // A收到B拒绝置换卡牌
		CardMod := p.PlayMod.getCardMod()
		CardInfo, ok := m.Extra.(card.CardInfo)
		if !ok {
			return nil
		}
		CardMod.AddExTimes(&CardInfo)
		p.AddCard(CardInfo.CardId)
		CardMod.DelExCard(&CardInfo)
		p.PushClientRes(CardMod.NotifyCard())
		p.PushClientRes(CardMod.NotifyTimes())
		p.PlayMod.save()
	case msg.HANDLE_TYPE_REFUSE_EX_CARD: // B收到A拒绝置换卡牌
		CardMod := p.PlayMod.getCardMod()
		CardInfo, ok := m.Extra.(card.CardInfo)
		if !ok {
			return nil
		}
		p.AddCard(CardInfo.ExId)
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.DelCardInfo(CardInfo.Id)
		if cardCfg.CheckCardIsGold(CardInfo.CardId) || cardCfg.CheckCardIsGold(CardInfo.ExId) {
			CardMod.AddGoldTimes()
		}
		p.PlayMod.save()
		p.PushClientRes(CardMod.NotifyCard())
	case msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY: // #  锦标赛排名变动通知
		p.BackChampship()
	case msg.HANDLE_TYPE_CHAMPSHIP_RESULT: // #  好友锦标赛结果
		Extra := GoUtil.IntSlice(m.Extra)
		p.AddLog(m.From, friend.LOG_TYPE_PLAYROOM_CHAMPSHIP, fmt.Sprintf("%d_%d", Extra[0], Extra[1]), m.SendT)
	case msg.HANDLE_TYPE_TREASURE_RESULT: // 好友宝藏结果
		// 暂未处理
	case msg.HANDLE_TYPE_MAIL: // 邮件操作
		SyncMailMsg(p)
	case msg.HANDLE_TYPE_PLAYROOM_LOSE: // #  玩家输了
		PlayroomMod := p.PlayMod.getPlayroomMod()
		Items := m.Item
		GameId := playroom.GAME_TYPE_HOOK
		Emoji := 0
		if m.Extra != nil {
			if val, ok := m.Extra.(GameResult); ok {
				GameId = val.T
				Emoji = val.Emoji
			}
		}
		if len(Items) == 0 {
			return nil
		}
		if GameId == playroom.GAME_TYPE_HOOK || GameId == playroom.GAME_TYPE_HIDE {
			PlayroomMod.AddChip(m.From, m.SendT, Emoji)
			p.AddLog(m.From, friend.LOG_TYPE_PLAYROOM_CAT_WIN, fmt.Sprintf("%d_%d_%d", Items[0].Id, Items[0].Num, Emoji), m.SendT)
		} else {
			p.AddLog(m.From, friend.LOG_TYPE_PLAYROOM_VISIT, fmt.Sprintf("%d_%d_%d", Items[0].Id, Items[0].Num, Emoji), m.SendT)
		}
		PlayroomMod.AddMood(playroom.MOOD_TYPE_FOOD, -50)
		PlayroomMod.AddMood(playroom.MOOD_TYPE_CLEAN, -50)
		PlayroomMod.AddVisitor(m.From, m.SendT)

		if Items[0].Id == item.ITEM_STAR_ID {
			BaseMod := p.PlayMod.getBaseMod()
			StarNum := BaseMod.GetStar()
			Items[0].Num = min(Items[0].Num, StarNum)
			p.HandleLoseItem(Items, "HANDLE_TYPE_PLAYROOM_LOSE")
		} else {
			PlayroomMod.Lose(Items)
		}
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.Interact(m.From, friend.INTERACT_TYPE_VISIT, m.SendT)
		p.UpdateUserInfo()
		p.TeLog("playroom_lost", map[string]interface{}{"uid": m.From, "item": Items})
		p.PushClientRes(PlayroomMod.NotifyLose())
	case msg.HANDLE_TYPE_PLAYROOM_GAME:
		FriendMod := p.PlayMod.getFriendMod()
		Emoji := 0
		if m.Extra != nil {
			if val, ok := m.Extra.(GameResult); ok {
				Emoji = val.Emoji
			}
		}
		p.AddLog(m.From, friend.LOG_TYPE_PLAYROOM_CAT_LOSE, fmt.Sprintf("%d", Emoji), m.SendT)
		FriendMod.Interact(m.From, friend.INTERACT_TYPE_VISIT, m.SendT)
	case msg.FRIEND_TREASURE_HANDLE: // #  好友宝藏
		Items, ok := m.Extra.([]*item.Item)
		if !ok {
			Items = []*item.Item{}
		}
		p.AddLog(m.From, friend.LOG_TYPE_TREASURE_HELP, "", m.SendT)
		p.HandleItem(Items, proto.ITEM_POP_LABEL_Friendtreasure.String())
	case msg.HANDLE_TYPE_HANDBOOK_COLLECTION: // 图鉴收集奖励
		if m.Extra == nil {
			return nil
		}
		data, ok := m.Extra.(msg.HandbookMsg)
		if !ok {
			return nil
		}
		p.AddLog(m.From, friend.LOG_TYPE_HANDBOOK, data.Type, m.SendT)
	case msg.HANDLE_TYPE_HANDBOOK_UPVOTE: // 图鉴点赞
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.Interact(m.From, friend.INTERACT_TYPE_UPVOTE, m.SendT)
		p.AddLog(m.From, friend.LOG_TYPE_HANDBOOK_UPVOTE, "", m.SendT)
	case msg.HANDLE_TYPE_SEND_CHARGE: // 收到好友赠送的充值礼包
		C, ok := m.Extra.(*ChargeExtra)
		if !ok {
			C = &ChargeExtra{}
		}
		PlayerSimpleData := G_GameLogicPtr.GetResSimplePlayerByUid(m.From)
		MailMod := p.PlayMod.getMailMod()
		mt, mc, mt_en, mc_en := mailCfg.GetChargeSendMail(PlayerSimpleData.Name)
		Items := p.ChargeItem(C.ChargeId)
		mailId := MailMod.SendMail(&mail.MailStruct{
			Title:     mt,
			Content:   mc,
			TitleEn:   mt_en,
			ContentEn: mc_en,
			Items:     Items,
			Type:      mail.MAIL_TYPE_GIFT,
		})
		p.AddLog(m.From, friend.LOG_TYPE_CHARGE_SEND, fmt.Sprintf("%d", mailId), m.SendT)
		p.PushClientRes(MailMod.NotifyMail(mailId))
	case msg.HANDLE_TYPE_CHARGE_RECEIVE: // 收到好友的感谢信
		Content, ok := m.Extra.(string)
		if !ok {
			Content = ""
		}
		PlayerSimpleData := G_GameLogicPtr.GetResSimplePlayerByUid(m.From)
		MailMod := p.PlayMod.getMailMod()
		mt, mc, mt_en, mc_en := mailCfg.GetChargeReceiveMail(PlayerSimpleData.Name, Content)
		mailId := MailMod.SendMail(&mail.MailStruct{
			Title:     mt,
			Content:   mc,
			TitleEn:   mt_en,
			ContentEn: mc_en,
			Type:      mail.MAIL_TYPE_NORMAL,
		})
		p.AddLog(m.From, friend.LOG_TYPE_CHARGE_RECEIVE, fmt.Sprintf("%d", mailId), m.SendT)
		p.PushClientRes(MailMod.NotifyMail(mailId))
	case msg.HANDLE_TYPE_WISHLIST_SEND: // 发送愿望单请求
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.AddWishApply(int64(m.From))
	case msg.HANDLE_TYPE_PLAYROOM_UPVOTE: // playroom点赞
		p.AddLog(m.From, friend.LOG_TYPE_PLAYROOM_UPVOTE, "", m.SendT)
		PlayroomMod := p.PlayMod.getPlayroomMod()
		PlayroomMod.AddUpvote()
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.Interact(m.From, friend.INTERACT_TYPE_VISIT, m.SendT)
		p.UpdateUserInfo()
	case msg.HANDLE_TYPE_WISHLIST_AGREE:
		ChargeMod := p.PlayMod.getChargeMod()
		ChargeMod.AddWishCount()
		p.AddLog(m.From, friend.LOG_TYPE_WISH, "", m.SendT)
		p.ChargeBackData()
	case msg.HANDLE_TYPE_PLAYROOM_KISS: // playroom亲吻
		p.NotifyPlayroomKiss()
	case msg.HANDLE_TYPE_CATNIP_INVITE: // 邀请好友参与猫咪游戏
		CatnipMod := p.PlayMod.getCatnipMod()
		CatnipMsg, ok := m.Extra.(CatnipMsg)
		if !ok {
			return nil
		}
		ActivityId := p.GetActivityId(activity.ACT_TYPE_CATNIP)
		if ActivityId != CatnipMsg.ActivityId { // 活动ID不匹配
			return nil
		}
		CatnipMod.BeInvited(int(m.From), m.SendT)
		FriendMod := p.PlayMod.getFriendMod()
		ReplyInfo := FriendMod.AddReplyInfo(m.From, friend.REPLY_TYPE_CATNIP, fmt.Sprintf("%d", CatnipMsg.GameId), m.End, nil)
		PlayerSimpleData := G_GameLogicPtr.GetResSimplePlayerByUid(m.From)
		p.PushClientRes(&proto.ResFriendReplyNotify{
			Info: &proto.ResFriendReply{
				Player: PlayerSimpleData,
				Param:  ReplyInfo.Param,
				Type:   int32(ReplyInfo.Type),
				Id:     int32(ReplyInfo.Id),
			},
			Type: int32(friend.REPLY_TYPE_CATNIP),
			Time: int32(m.SendT),
		})
	case msg.HANDLE_TYPE_CATNIP_AGREE: // 同意好友参与猫咪游戏
		CatnipMod := p.PlayMod.getCatnipMod()
		CatnipMsg, ok := m.Extra.(CatnipMsg)
		if !ok {
			return nil
		}
		ActivityId := p.GetActivityId(activity.ACT_TYPE_CATNIP)
		if ActivityId != CatnipMsg.ActivityId { // 活动ID不匹配
			return nil
		}
		CatnipMod.BeAgree(CatnipMsg.GameId, int(m.From))
	case msg.HANDLE_TYPE_CATNIP_AGREE_DEL: // 同意好友参与猫咪游戏后删除邀请
		CatnipMod := p.PlayMod.getCatnipMod()
		CatnipMsg, ok := m.Extra.(CatnipMsg)
		if !ok {
			return nil
		}
		ActivityId := p.GetActivityId(activity.ACT_TYPE_CATNIP)
		if ActivityId != CatnipMsg.ActivityId { // 活动ID不匹配
			return nil
		}
		CatnipMod.DelInvited(CatnipMsg.GameId, int(m.From))
	case msg.HANDLE_TYPE_CATNIP_REFUSE: // 拒绝好友参与猫咪游戏
		CatnipMod := p.PlayMod.getCatnipMod()
		CatnipMsg, ok := m.Extra.(CatnipMsg)
		if !ok {
			return nil
		}
		ActivityId := p.GetActivityId(activity.ACT_TYPE_CATNIP)
		if ActivityId != CatnipMsg.ActivityId { // 活动ID不匹配
			return nil
		}
		CatnipMod.DelInvited(CatnipMsg.GameId, int(m.From))
	case msg.HANDLE_TYPE_CATNIP_GROWTH:
		CatnipMod := p.PlayMod.getCatnipMod()
		CatnipMsg, ok := m.Extra.(CatnipMsg)
		if !ok {
			return nil
		}
		ActivityId := p.GetActivityId(activity.ACT_TYPE_CATNIP)
		if ActivityId != CatnipMsg.ActivityId { // 活动ID不匹配
			return nil
		}
		CatnipMod.GrowthByUid(m.From, CatnipMsg.Growth)
		if CatnipMsg.FriendItems > 0 {
			Items := catnipCfg.GetItemCost(ActivityId, CatnipMsg.FriendItems)
			FriendMod := p.PlayMod.getFriendMod()
			ReplyInfo := FriendMod.AddReplyInfo(m.From, friend.REPLY_TYPE_CATNIP_ITEMS, "", m.End, Items)
			PlayerSimpleData := G_GameLogicPtr.GetResSimplePlayerByUid(m.From)
			p.PushClientRes(&proto.ResFriendReplyNotify{
				Info: &proto.ResFriendReply{
					Player: PlayerSimpleData,
					Param:  ReplyInfo.Param,
					Type:   int32(ReplyInfo.Type),
					Id:     int32(ReplyInfo.Id),
				},
				Type: int32(friend.REPLY_TYPE_CATNIP_ITEMS),
				Time: int32(m.SendT),
			})
		}
		p.CatnipBackData()
	case msg.HANDLE_TYPE_CATNIP_SEND_EMOJI:
		CatnipMod := p.PlayMod.getCatnipMod()
		EmojiId := GoUtil.Int(m.Extra)
		CatnipMod.SetEmoji(m.From, EmojiId)
		p.CatnipBackData()
	case msg.HANDLE_TYPE_FRIEND_GREETING_REPLY:
		FriendMod := p.PlayMod.getFriendMod()
		if v, ok := m.Extra.(friend.ReplyInfo); ok {
			FriendMod.AddReplyInfo(v.Uid, v.Type, v.Param, GoUtil.Now()+oneday, nil)
			p.FriendLogBackData()
		}
	case msg.HANDLE_TYPE_FRIEND_SPONSOER:
		p.AddLog(m.From, friend.LOG_TYPE_FRIEND_SPONSOR_GET, "", m.SendT)
	case msg.SERVER_PLAYER_SYNC_LOGOUT_MSG:
		//p.LoginBackData()
	default:
		log.Debug("uid : %d, handle msg type : %d not exist", p.M_DwUin, m.Type)
	}
	return nil
}

func SyncMailMsg(p *Player) {
	ServerMailList := G_GameLogicPtr.MailMgr.Sync(int(p.M_DwUin), p.GetPlayerBaseMod().GetRegisterTime())
	MailMod := p.PlayMod.getMailMod()
	for _, v := range ServerMailList {
		if GoUtil.InArray(v.Id, MailMod.ServerMail) {
			continue
		}
		MailMod.ServerMail = append(MailMod.ServerMail, v.Id)
		MailMod.SendMail(&mail.MailStruct{
			Title:          v.Title,
			Content:        v.Content,
			TitleEn:        v.TitleEn,
			ContentEn:      v.ContentEn,
			TitlePtBr:      v.TitlePtBr,
			ContentPtBr:    v.ContentPtBr,
			TitleEsLatam:   v.TitleEsLatam,
			ContentEsLatam: v.ContentEsLatam,
			Items:          v.Items,
			Type:           v.Mail_type,
		})
	}
	p.PushClientRes(MailMod.BackData())
}

func (p *Player) CatnipGrowthMsg(To, Id, Growth, FriendItems int) error {
	ActivityId := p.GetActivityId(activity.ACT_TYPE_CATNIP)
	FriendMgrSend(&msg.Msg{
		From:  int(p.M_DwUin),
		To:    To,
		Type:  msg.HANDLE_TYPE_CATNIP_GROWTH,
		SendT: GoUtil.Now(),
		Extra: CatnipMsg{
			ActivityId:  ActivityId,
			GameId:      Id,
			Growth:      Growth,
			FriendItems: FriendItems,
		},
	})
	return nil
}

// 发送消息给玩家
func ClusterSendMsg(ServerId int, m *msg.Msg) {
	mergeCluster.SendServerMsg(m, ServerId)
}

func GetCardInfoMsg(CardInfo *card.CardInfo) *proto.ResFriendCard {
	Uid := 0
	if CardInfo.Type == card.TYPE_CARD_SEND {
		Uid = CardInfo.BUid
	}

	if CardInfo.Type == card.TYPE_CARD_GIVE {
		if CardInfo.Status == card.STATUS_CARD_GIVE_1 {
			Uid = CardInfo.AUid
		} else {
			Uid = CardInfo.BUid
		}
	}

	if CardInfo.Type == card.TYPE_CARD_EX {
		if CardInfo.Status == card.STATUS_CARD_EX_2 {
			Uid = CardInfo.AUid
		} else {
			Uid = CardInfo.BUid
		}
	}

	ps := G_GameLogicPtr.GetSimplePlayerByUid(Uid)
	if ps == nil {
		return &proto.ResFriendCard{}
	}
	return &proto.ResFriendCard{
		Uid:      int64(Uid),
		Name:     ps.Name,
		Face:     int32(ps.Face),
		Avatar:   int32(ps.Avatar),
		Level:    int32(ps.Level),
		CardId:   int32(CardInfo.CardId),
		ExCardId: int32(CardInfo.ExId),
		Time:     int32(CardInfo.StartTime),
		Type:     int32(CardInfo.Type),
		Status:   int32(CardInfo.Status),
		Id:       CardInfo.Id,
		Emoji:    int32(CardInfo.Emoji),
	}
}

// 发射器退役第一步 不再生成此发射器订单
func (p *Player) EmitRetireTrigger1() {
	ChessMod := p.PlayMod.getChessMod()
	EmitList := ChessMod.GetEmitList()
	EmitId := make(map[string]struct{})
	for _, v := range EmitList {
		Emit_Id := mergeDataCfg.GetEmitId(v)
		if Emit_Id == "" {
			continue
		}
		EmitId[Emit_Id] = struct{}{}
	}
	var EmitId1 []string
	for k := range EmitId {
		EmitId1 = append(EmitId1, k)
	}
	if len(EmitId1) <= 5 {
		return
	}
	sort.Slice(EmitId1, func(i, j int) bool {
		return EmitId1[i] < EmitId1[j]
	})
	OrderMod := p.PlayMod.getOrderMod()
	OrderMod.Retire(EmitId1[0])
	p.TeLog("launcher_retire", map[string]interface{}{
		"launcher_type": EmitId1[0],
	})
	ChessMod.BeginRetire(EmitId1[0])
}

// 发射器退役第二步 生成清理订单
func (p *Player) EmitRetireTrigger2() {
	ChessMod := p.PlayMod.getChessMod()
	OrderMod := p.PlayMod.getOrderMod()
	BaseMod := p.PlayMod.getBaseMod()
	OrderList := OrderMod.GetOrderList()
	AllChess := make(map[string]struct{})
	for _, v := range OrderList {
		for _, v1 := range v.MergeId {
			Color := mergeDataCfg.GetColorById(v1)
			AllChess[Color] = struct{}{}
		}
	}
	RetireEmit := ChessMod.GetRetireEmit()
	for k, v := range RetireEmit {
		if k == "" {
			continue
		}
		if v != 1 {
			continue
		}
		RetireLv := mergeDataCfg.GetEmitRetire(k)
		if RetireLv > BaseMod.GetLevel() {
			continue
		}

		NeedFinishOrder := false
		Produce := mergeDataCfg.GetEmitOrderProduce(k)
		for _, v1 := range Produce {
			if _, ok := AllChess[v1]; ok {
				NeedFinishOrder = true
				break
			}
		}
		if NeedFinishOrder {
			continue
		}
		ChessMod.RetireOrder(k)
	}
	for _, v := range OrderList {
		if v.Type == order.Clean_type {
			return
		}
	}
	RetireEmit1 := ChessMod.GetRetireEmit()
	for k, v := range RetireEmit1 {
		if k == "" {
			continue
		}
		if v != 2 {
			continue
		}
		ChessList := ChessMod.GetRetireChess(k)
		// 清理完成
		if len(ChessList) == 0 {
			ChessMod.FinishRetire(k)
			ChargeMod := p.PlayMod.getChargeMod()
			ChargeMod.InitChessShop(ChessMod.GetEmitList())
			p.ChargeBackData()
			continue
		}
		OrderMod.CreateCleanOrder(ChessList)
		return
	}
}

func NotifyChampshipResult(Uid, Rank int) {
	PlayerSimpleData := G_GameLogicPtr.GetSimplePlayerByUid(Uid)
	if PlayerSimpleData == nil {
		return
	}
	now := GoUtil.Now()
	serveropenday := GoUtil.GetServerOpenDay()
	for _, v := range PlayerSimpleData.Friend {
		if CheckPlayerLose(v) {
			continue
		}
		SendPlayerMsgAsync(&msg.Msg{
			Type:  msg.HANDLE_TYPE_CHAMPSHIP_RESULT,
			From:  Uid,
			To:    v,
			SendT: now,
			End:   now + sevendays,
			Extra: []int{Rank, serveropenday},
		})
	}
}

func (player *Player) GetPetOrderItemExp() int {
	OrderItemCfgList := playroomCfg.GetOrderItemList()
	itemList := make([]*item.Item, 0)
	ItemMod := player.PlayMod.getItemMod()
	for _, v := range OrderItemCfgList {
		Num := ItemMod.GetItem(v)
		if Num <= 0 {
			continue
		}
		itemList = append(itemList, &item.Item{
			Id:  v,
			Num: Num,
		})
	}
	return playroomCfg.GetPetOrderItemExpByList(itemList)
}

// 触发生成新的固定订单
func (player *Player) TriggerOrder(lv int, Type string, Emit []int, EnergyMul int) error {
	OrderMod := player.PlayMod.getOrderMod()
	TriggerOrderList := orderCfg.GetStartOrderList()
	FixedOrder := 0
	for _, v := range OrderMod.OrderList {
		if v.Type == order.Fixed_type {
			FixedOrder++
		}
	}
	OrderList := make(map[int]order.Order, len(OrderMod.OrderList))
	for k, v := range OrderMod.OrderList {
		OrderList[k] = v
	}
	// 触发生成新的固定订单
	for _, v := range TriggerOrderList {
		if GoUtil.InArray(v.Id, OrderMod.FinishOrder) {
			continue
		}
		orderInfo, exists := OrderList[v.Id]
		if exists && v.Preview == "" {
			continue
		}
		// 预览条件不为空且未存在且未完成
		if v.Preview != "" && !exists && !GoUtil.InArray(v.Id, OrderMod.FinishOrder) {
			if OrderMod.CheckCondition(lv, v.Preview, Type, Emit, FixedOrder, OrderList) {
				OrderMod.AddFixOrder(v.Id, v.MergeList, order.Preview_type, v.Items)
			}
		}

		if v.Appear != "" {
			if OrderMod.CheckCondition(lv, v.Appear, Type, Emit, FixedOrder, OrderList) {
				Type := order.Fixed_type
				OrderType := orderCfg.GetOrderType(v.Id)
				if OrderType != 0 {
					Type = OrderType
				}
				player.TeLog("preset_order_birth", map[string]interface{}{
					"order_id":           v.Id,
					"order_item_id":      v.MergeList,
					"preset_order_group": v.Group,
					"preset_order_step":  v.Step,
				})
				if exists {
					orderInfo.Type = order.Fixed_type
					OrderMod.OrderList[v.Id] = orderInfo
				} else {
					OrderMod.AddFixOrder(v.Id, v.MergeList, Type, v.Items)
					if v.Id == 78 {
						OrderMod.Retire("D")
						OrderMod.AutoEmit = append(OrderMod.AutoEmit, "D")
					}
					if v.Id == 79 {
						OrderMod.Retire("I")
						OrderMod.AutoEmit = append(OrderMod.AutoEmit, "I")
					}
				}
			}
		}
	}
	return nil
}
func (player *Player) AddOrder() {
	BaseMod := player.PlayMod.getBaseMod()
	OrderMod := player.PlayMod.getOrderMod()
	ChessMod := player.PlayMod.getChessMod()
	MaxOrderNum := orderCfg.GetOrderNum(BaseMod.GetLevel())
	n := 0
	if OrderMod.LastOrder.Type == order.Preheat_type {
		ChessId := OrderMod.LastOrder.MergeId[0]
		ChessColor := mergeDataCfg.GetColorById(ChessId)
		PreheatStep := OrderMod.PreheatStep[ChessColor]
		OrderMod.PreheatStep[ChessColor]++
		if PreheatStep < 4 {
			NewChessId := mergeDataCfg.GetChessIdByLvAndColor(BaseMod.GetEnergyMul()+PreheatStep+1, ChessColor)
			Items, ok := order.PreheatItems[OrderMod.PreheatStep[ChessColor]]
			if !ok {
				Items = []*item.Item{item.NewItem(item.ITEM_STAR_ID, order.GetOrderStar([]int{NewChessId}, ChessMod.GetOrderEmit()))}
			}
			OrderMod.AddPreheatOrder([]int{NewChessId}, order.DIFF_LOW, order.Preheat_type, Items)
		}
	}
	for _, v := range OrderMod.OrderList {
		if v.Type == order.Common_type || v.Type == order.Pet_type || v.Type == order.Part_type || v.Type == order.Fixed_type || v.Type == order.Preview_type {
			n++
		}
	}
	for i := n; i < MaxOrderNum; i++ {
		player.CreateNormalOrder()
	}
}

func (player *Player) FixOrderBug() {
	OrderMod := player.PlayMod.getOrderMod()
	BaseMod := player.PlayMod.getBaseMod()
	ChessMod := player.PlayMod.getChessMod()
	for k, v := range OrderMod.PreheatStep {
		if v > 4 {
			continue
		}
		Exit := false
		for _, o := range OrderMod.OrderList {
			if o.Type != order.Preheat_type {
				continue
			}
			Color := mergeDataCfg.GetColorById(o.MergeId[0])
			if Color == k {
				Exit = true
				break
			}

		}
		if Exit {
			continue
		}
		NewChessId := mergeDataCfg.GetChessIdByLvAndColor(BaseMod.GetEnergyMul()+v+1, k)
		OrderMod.PreheatStep[k]++
		Items, ok := order.PreheatItems[OrderMod.PreheatStep[k]]
		if !ok {
			Items = []*item.Item{item.NewItem(item.ITEM_STAR_ID, order.GetOrderStar([]int{NewChessId}, ChessMod.GetOrderEmit()))}
		}
		OrderMod.AddPreheatOrder([]int{NewChessId}, order.DIFF_LOW, order.Preheat_type, Items)
	}
}

func (player *Player) FixDecorate() {
	DecorateMod := player.PlayMod.getDecorateMod()
	area_id := DecorateMod.GetAreaId()
	progress := DecorateMod.GetProgress()
	if GoUtil.InArray(area_id, []int{3, 4, 5}) && progress >= 20 {
		items := []*item.Item{}
		for i := progress + 1; i <= 25; i++ {
			if area_id == 3 && i == 25 {
				items = append(items, item.NewItem(item.ITEM_ENERGY_ID, 50))
				items = append(items, item.NewItem(101449, 1))
			}
			if area_id == 4 && i == 22 {
				items = append(items, item.NewItem(906, 1))
			}
			if area_id == 4 && i == 25 {
				items = append(items, item.NewItem(item.ITEM_ENERGY_ID, 50))
				items = append(items, item.NewItem(101452, 1))
			}
			if area_id == 5 && i == 25 {
				items = append(items, item.NewItem(item.ITEM_ENERGY_ID, 50))
				items = append(items, item.NewItem(101450, 1))
			}
		}
		title := "Game Update & Thank-You Gift"
		content := `Hi there!

Thanks so much for your continued support! 
We've made a few updates to the game—and as a small thank-you, we've prepared a special gift for you.

Happy merging!

Meowment Team`
		title_ptbr := "Atualização do Jogo e Presente de Agradecimento"
		content_ptbr := `Olá!

Muito obrigado pelo seu apoio contínuo!
Fizemos algumas atualizações no jogo — e como forma de agradecimento, preparamos um presente especial para você.

Boa diversão nas combinações! 

Equipe Meowment `

		MailMod := player.PlayMod.getMailMod()
		MailMod.SendMail(&mail.MailStruct{
			Title:       title,
			Content:     content,
			TitleEn:     title,
			ContentEn:   content,
			TitlePtBr:   title_ptbr,
			ContentPtBr: content_ptbr,
			Items:       items,
			Type:        mail.MAIL_TYPE_NORMAL,
		})
		DecorateMod.AreaId = area_id + 1
		DecorateMod.FinishList = make(map[int]struct{})
		DecorateMod.Progress = 0
		DecorateMod.PartCost = make(map[int]*decorate.PartCostInfo)
		DecorateMod.PartClassPool = []int{}
		DecorateMod.PartPool = make(map[int]int)
		DecorateMod.InitData()
		log.Debug("player id : %d fix decorate old area id : %d old progress : %d", player.M_DwUin, area_id, progress)
		player.PushClientRes(DecorateMod.BackData())
	}
}

func (player *Player) CreatePetOrder() {
	BaseMod := player.PlayMod.getBaseMod()
	ChessMod := player.PlayMod.getChessMod()
	OrderMod := player.PlayMod.getOrderMod()
	PetTrigger := true
	for _, v := range OrderMod.GetOrderList() {
		if v.Type == order.Pet_type {
			PetTrigger = false
			break
		}
	}
	if PetTrigger && BaseMod.GetLevel() >= 17 {
		OrderMod.CreateOrder(BaseMod.GetLevel(), ChessMod.GetOrderEmit(), BaseMod.GetEnergyMul(), order.Pet_type)
		for k, v := range OrderMod.GetOrderList() {
			if len(v.Items) != 0 {
				continue
			}
			if v.Type != order.Pet_type {
				continue
			}
			var Items []*item.Item
			Star := order.GetOrderStar(v.MergeId, ChessMod.GetStarEmitList())
			// Star = int(float64(Star)*float64(OrderFactor)/1000) * 10
			Items = player.GetPetOrderReward(Star, Items)
			if len(Items) == 1 && Items[0].Id == item.ITEM_STAR_ID {
				v.Type = order.Common_type
			} else {
				v.Type = order.Pet_type
			}
			v.Items = Items
			OrderMod.OrderList[k] = v
		}
		return
	}
}

func (player *Player) CreateNormalOrder() {
	Exp, PExp := userCfg.GetLevUpExp(player.GetPlayerBaseMod().GetLevel())
	BaseMod := player.PlayMod.getBaseMod()
	DecorateMod := player.PlayMod.getDecorateMod()
	ChessMod := player.PlayMod.getChessMod()
	OrderFactor := orderCfg.GetOrderFactor(DecorateMod.GetAreaId())
	ExpCoin := (Exp-BaseMod.GetExp())*decorateCfg.GetAreaPerPExp(DecorateMod.GetAreaId()) - BaseMod.GetStar()
	PExpCoin := (PExp-BaseMod.GetPExp())*50 - player.GetPetOrderItemExp()
	OrderMod := player.PlayMod.getOrderMod()

	// 预热订单

	// 安慰订单
	Now := GoUtil.Now()
	if OrderMod.LastOrder.Type == order.COMFORT_TYPE && Now < int64(OrderMod.ComfortEndTime) {
		OrderMod.CreateOrder(BaseMod.GetLevel(), ChessMod.GetOrderEmit(), BaseMod.GetEnergyMul(), order.COMFORT_TYPE)
		for k, v := range OrderMod.GetOrderList() {
			if k == OrderMod.Auto_id {
				if v.Type != order.COMFORT_TYPE {
					continue
				}
				Star := order.GetOrderStar(v.MergeId, ChessMod.GetOrderEmit())
				Star = int(float64(Star)*float64(OrderFactor)/1000) * 10
				v.Items = []*item.Item{{Id: item.ITEM_STAR_ID, Num: Star}}
				OrderMod.OrderList[k] = v
			}
		}
		return
	}

	PetTrigger := true
	for _, v := range OrderMod.GetOrderList() {
		if v.Type == order.Pet_type {
			PetTrigger = false
			break
		}
	}
	if PExpCoin > ExpCoin && PetTrigger && BaseMod.GetLevel() >= 17 {
		OrderMod.CreateOrder(BaseMod.GetLevel(), ChessMod.GetOrderEmit(), BaseMod.GetEnergyMul(), order.Pet_type)
		for k, v := range OrderMod.GetOrderList() {
			if len(v.Items) != 0 {
				continue
			}
			if v.Type != order.Pet_type {
				continue
			}
			var Items []*item.Item
			Star := order.GetOrderStar(v.MergeId, ChessMod.GetStarEmitList())
			// Star = int(float64(Star)*float64(OrderFactor)/1000) * 10
			Items = player.GetPetOrderReward(Star, Items)
			if len(Items) == 1 && Items[0].Id == item.ITEM_STAR_ID {
				v.Type = order.Common_type
			} else {
				v.Type = order.Pet_type
			}
			v.Items = Items
			OrderMod.OrderList[k] = v
		}
		return
	}

	// 触发式订单 满足条件生成零件订单
	PartCost := DecorateMod.GetPartCost()
	PartBag := ChessMod.GetPartBag()
	Trigger := true
	for _, v := range OrderMod.GetOrderList() {
		if v.Type == order.Part_type {
			Trigger = false
		}
	}
	Trigger2 := false
	for k, v := range PartCost {
		if v > PartBag[k] {
			Trigger2 = true
		}
	}
	if Trigger && Trigger2 && BaseMod.GetLevel() >= 12 {
		OrderMod.CreateOrder(BaseMod.GetLevel(), ChessMod.GetOrderEmit(), BaseMod.GetEnergyMul(), order.Part_type)
		for k, v := range OrderMod.GetOrderList() {
			if v.Type == order.Part_type {
				v.Items = []*item.Item{item.NewItem(item.ITEM_LAUNCHER_ID, 2)}
				OrderMod.OrderList[k] = v
			}
		}
		return
	}
	OrderMod.CreateOrder(BaseMod.GetLevel(), ChessMod.GetOrderEmit(), BaseMod.GetEnergyMul(), order.Common_type)

}
func (player *Player) InitOrderItem() {
	OrderMod := player.PlayMod.getOrderMod()
	DecorateMod := player.PlayMod.getDecorateMod()
	ChessMod := player.PlayMod.getChessMod()
	OrderFactor := orderCfg.GetOrderFactor(DecorateMod.GetAreaId())
	for k, v := range OrderMod.GetOrderList() {
		if v.Type == order.Super_type {
			continue
		}
		if len(v.Items) != 0 {
			continue
		}
		Star := order.GetOrderStar(v.MergeId, ChessMod.GetStarEmitList())
		Star = int(float64(Star)*float64(OrderFactor)/1000+0.5) * 10
		v.Items = []*item.Item{{Id: item.ITEM_STAR_ID, Num: Star}}
		OrderMod.OrderList[k] = v
	}
}
func (player *Player) GetPetOrderReward(Star int, Items []*item.Item) []*item.Item {
	HighNum := Star / 225
	if HighNum > 0 {
		HighNum = min(HighNum, 3)
		Items = append(Items, item.NewItem(item.ITEM_PLAYROOM_BOX_HIGH_ID, HighNum))
		Star -= HighNum * 225
	}

	MidNum := Star / 150
	if MidNum > 0 {
		MidNum = min(MidNum, 3)
		Items = append(Items, item.NewItem(item.ITEM_PLAYROOM_BOX_MID_ID, MidNum))
		Star -= MidNum * 150
	}
	if len(Items) >= 2 {
		Items = append(Items, item.NewItem(item.ITEM_STAR_ID, Star))
		return Items
	}
	LowNum := Star / 75
	if LowNum > 0 {
		LowNum = min(LowNum, 3)
		Items = append(Items, item.NewItem(item.ITEM_PLAYROOM_BOX_LOW_ID, LowNum))
		Star -= LowNum * 75
	}
	if Star > 0 {
		Items = append(Items, item.NewItem(item.ITEM_STAR_ID, Star))
	}
	return Items
}

func ExcludeCardStar(CardList []int) []int {
	StarList := make([]int, 0, len(CardList))
	for _, v := range CardList {
		Star := cardCfg.GetStarById(v)
		if Star < 2 || Star > 4 {
			continue
		}
		StarList = append(StarList, v)
	}
	return StarList
}

func (p *Player) GetPlayroomGameReward(Type, SelectId int) []*item.Item {
	PlayroomMod := p.PlayMod.getPlayroomMod()
	BaseMod := p.PlayMod.getBaseMod()
	Level := BaseMod.GetLevel()
	var Items []*item.Item
	switch Type {
	case playroom.GAME_RESULT_LOSE:
		Items = append(Items, item.NewItem(item.ITEM_STAR_ID, 20))
	case playroom.GAME_RESULT_LOW:
		Items = append(Items, item.NewItem(item.ITEM_STAR_ID, Level*2))
	case playroom.GAME_RESULT_MIDDLE:
		Items = append(Items, item.NewItem(item.ITEM_STAR_ID, Level*3))
	default:
		Items = PlayroomMod.SelectReward(SelectId)
	}
	return Items
}

func (p *Player) GetPetThiefReward(Target int) error {
	PlayerData := G_GameLogicPtr.GetSimplePlayerByUid(Target)
	if PlayerData == nil {
		return fmt.Errorf("target %d not exist", Target)
	}
	CardStar := limitedTimeEventCfg.GetThiefProb()
	starMap := make(map[int][]int)
	var cardList []int
	for _, v := range PlayerData.CardInfo {
		Star := cardCfg.GetStarById(v)
		starMap[Star] = append(starMap[Star], v)
	}
	for {
		if l, ok := starMap[CardStar]; ok {
			cardList = l
			break
		}
		if CardStar <= 1 {
			break
		}
		CardStar--
	}
	ItemId := 0
	if len(cardList) == 0 {
		List := cardCfg.GetCardListByStar(0, 1, 0)
		CardId := GoUtil.RandSlice(List)
		ItemId = cardCfg.GetItemIdByCardId(CardId)
		if ItemId == 0 {
			log.Error("LimitEventPetTheif ItemId %d not exist", ItemId)
			return fmt.Errorf("ItemId %d not exist", ItemId)
		}
	} else {
		CardId := GoUtil.RandSlice(cardList)
		ItemId = cardCfg.GetItemIdByCardId(CardId)
	}
	p.HandleItem([]*item.Item{{Id: ItemId, Num: 1}}, proto.ITEM_POP_LABEL_PetTheif.String())
	return nil
}

// 高级产物订单
func (p *Player) AddHighOrder() {
	OrderMod := p.PlayMod.getOrderMod()
	BaseMod := p.PlayMod.getBaseMod()
	ChessMod := p.PlayMod.getChessMod()
	LastChess := OrderMod.LastOrder.MergeId[len(OrderMod.LastOrder.MergeId)-1]
	maxId := 0
	for k := range OrderMod.GetOrderList() {
		maxId = max(maxId, k)
	}
	if maxId == 0 || BaseMod.GetLevel() < 12 {
		return
	}
	NewChess := OrderMod.GetOrderList()[maxId].MergeId[0]
	LastColor := mergeDataCfg.GetColorById(LastChess)
	NewColor := mergeDataCfg.GetColorById(NewChess)
	LastEmitId := order.GetEmitByColor(ChessMod.GetOrderEmit(), LastColor)
	AddNewEmitId := order.GetEmitByColor(ChessMod.GetOrderEmit(), NewColor)
	var Product []string
	Product = append(Product, mergeDataCfg.GetEmitProduceType(LastEmitId)...)
	Product = append(Product, mergeDataCfg.GetEmitProduceType(AddNewEmitId)...)
	ChessMap := make(map[string]int)
	ChessList := ChessMod.GetUnlockChessList()
	for _, v := range ChessList {
		ChessType := mergeDataCfg.GetTypeById(v)
		if ChessType != "Product" {
			continue
		}
		Color := mergeDataCfg.GetColorById(v)
		if GoUtil.InStringArray(Color, Product) {
			continue
		}
		if v > ChessMap[Color] {
			ChessMap[Color] = v
		}
	}

	for Color, ChessId := range ChessMap {
		EmitId := order.GetEmitByColor(ChessMod.GetOrderEmit(), Color)
		_, ChessMaxLv := getChesslvRange(EmitId, BaseMod.GetEnergyMul(), OrderMod.IsCharge)
		NewLev2 := mergeDataCfg.DynamicLev(ChessMaxLv, EmitId, Color)
		NewLev3 := order.AdjustLev(NewLev2, BaseMod.GetEnergyMul())
		ChessLv := mergeDataCfg.GetLvById(ChessId)
		if NewLev3 >= ChessLv {
			continue
		}
		Add := true
		for _, v := range OrderMod.GetOrderList() {
			if GoUtil.InArray(ChessId, v.MergeId) {
				Add = false
			}
		}
		if Add {
			OrderMod.AddExtraOrder([]int{ChessId})
			return
		}
	}
}

// 高级产物订单
/**
当玩家生成了两个一样的最高等级产物，自动生成一个订单收掉它们。
注意：当现有订单（无论是自动或固定订单）中已有两个或三个最高等级产物订单的时候，不执行此逻辑
*/
func (p *Player) AddHighOrder2() {
	OrderMod := p.PlayMod.getOrderMod()
	ChessMod := p.PlayMod.getChessMod()
	ChessList := ChessMod.GetUnlockChessList()
	ChessMap := make(map[int]int)
	for _, v := range ChessList {
		Lv := mergeDataCfg.GetLvById(v)
		MaxLv := mergeDataCfg.GetMaxLvById(v)
		if Lv != MaxLv {
			continue
		}
		Type := mergeDataCfg.GetTypeById(v)
		if Type != "Product" {
			continue
		}
		ChessMap[v]++
	}
	for ChessId, Num := range ChessMap {
		if Num < 2 {
			continue
		}
		add := true
		for _, v := range OrderMod.GetOrderList() {
			if GoUtil.SliceEqual(v.MergeId, []int{ChessId, ChessId}) || GoUtil.SliceEqual(v.MergeId, []int{ChessId, ChessId, ChessId}) {
				add = false
				break
			}
		}
		if add {
			OrderMod.AddExtraOrder([]int{ChessId, ChessId})
			return
		}
	}
}

func (p *Player) FormatPetOrderItem(Items []*item.Item) []*item.Item {
	var NewItems []*item.Item
	PlayroomMod := p.PlayMod.getPlayroomMod()
	for _, v := range Items {
		if v.Id != item.ITEM_PLAYROOM_BOX_LOW_ID && v.Id != item.ITEM_PLAYROOM_BOX_MID_ID && v.Id != item.ITEM_PLAYROOM_BOX_HIGH_ID {
			NewItems = append(NewItems, v)
			continue
		}
		var OrderItem map[int][]int
		switch v.Id {
		case item.ITEM_PLAYROOM_BOX_LOW_ID:
			OrderItem = playroomCfg.GetOrderItemByGrade(1)
		case item.ITEM_PLAYROOM_BOX_MID_ID:
			OrderItem = playroomCfg.GetOrderItemByGrade(2)
		default:
			OrderItem = playroomCfg.GetOrderItemByGrade(3)
		}
		feed := PlayroomMod.GetPhysiology(playroom.PHYSIOLOGY_TYPE_FEED)
		feedItem := p.GetPlayroomFood()
		feedPlo := playroomCfg.GetItemAddPhysiology(feedItem)
		if feed != nil && feed.Num+feedPlo <= 1 {
			RandList := OrderItem[1]
			NewItems = append(NewItems, item.NewItem(GoUtil.RandSlice(RandList), 1))
			continue
		}
		clean := PlayroomMod.GetPhysiology(playroom.PHYSIOLOGY_TYPE_CLEAN)
		cleanItem := p.GetPlayroomClean()
		cleanPlo := playroomCfg.GetItemAddPhysiology(cleanItem)
		// 卫生值低于等于5点，优先产出清洁类物品
		if clean != nil && clean.Num+cleanPlo <= 5 {
			RandList := OrderItem[2]
			NewItems = append(NewItems, item.NewItem(GoUtil.RandSlice(RandList), 1))
			continue
		}
		var RandList []int
		for k, v1 := range OrderItem {
			if k == 1 || k == 2 {
				continue
			}
			RandList = append(RandList, v1...)
		}
		NewItems = append(NewItems, item.NewItem(GoUtil.RandSlice(RandList), 1))
	}
	return NewItems
}

func (player *Player) GetPlayroomFood() map[int]int {
	ItemMod := player.PlayMod.getItemMod()
	Item := make(map[int]int)
	for k, v := range ItemMod.Data {
		ItemType := itemCfg.GetItemType(k)
		if ItemType == item.ITEM_TYPE_PLAYROOM_PET {
			Effect := itemCfg.GetItemEffect(k)
			if Effect == 1 {
				Item[k] = v
			}
		}
	}
	return Item
}

func (player *Player) GetPlayroomClean() map[int]int {
	ItemMod := player.PlayMod.getItemMod()
	Item := make(map[int]int)
	for k, v := range ItemMod.Data {
		ItemType := itemCfg.GetItemType(k)
		if ItemType == item.ITEM_TYPE_PLAYROOM_PET {
			Effect := itemCfg.GetItemEffect(k)
			if Effect == 2 {
				Item[k] = v
			}
		}
	}
	return Item
}

func (player *Player) IsWeeklyDiscount() bool {
	ChargeMod := player.PlayMod.getChargeMod()
	LimitEventMod := player.PlayMod.getLimitedTimeEventMod()
	return ChargeMod.IsWeeklyDiscountDay() || LimitEventMod.CheckExist(limitedTimeEvent.EVENT_TYPE_CAT_DAY_SALE)
}

func (p *Player) SetCatnipPartner(GameId, Partner int, EndTime int64) error {
	_, err := SendMsgToCenterSync(&msg.Msg{
		From: int(p.M_DwUin),
		To:   int(p.M_DwUin),
		Type: msg.HANDLE_MOD_CATNIP_PARTNER,
		Extra: CatnipPartner{
			GameId:  GameId,
			Partner: Partner,
			EndTime: EndTime,
			Uid:     int(p.M_DwUin),
		},
	})
	return err
}
