package game

import (
	"fmt"
	"math"
	playroomCfg "server/conf/playroom"
	userCfg "server/conf/user"
	"server/game/mod/card"
	"server/game/mod/item"
	limitedTimeEvent "server/game/mod/limited_time_event"
	MsgMod "server/game/mod/msg"
	"server/game/mod/playroom"
	GoUtil "server/game_util"
	"server/msg"
	"time"
)

// 限时事件触发器
func (p *Player) LimitedTimeEventTrigger(AddEventId int) {
	Lv := p.GetPlayerBaseMod().GetLevel()
	EndTime, TimeoutEvent, AddEvent := p.PlayMod.getLimitedTimeEventMod().Trigger(Lv)
	remainingTime := GoUtil.NextHourRemain()
	if EndTime <= 0 {
		EndTime = int(remainingTime)
	} else {
		EndTime = min(EndTime, int(remainingTime))
	}
	if AddEventId != 0 {
		AddEvent = append(AddEvent, AddEventId)
	}
	if EndTime > 0 {
		p.CallEvent(time.Duration(EndTime)*time.Second, func() {
			p.lock.Lock()
			defer p.lock.Unlock()
			p.LimitedTimeEventTrigger(0)
			p.SendClientRes()
		}, "LimitedTimeEvent")
	}

	for _, v := range TimeoutEvent { // 事件到期处理
		p.PushClientRes(&msg.LimitEventNotify{
			Id:   int32(v),
			Type: limitedTimeEvent.EVENT_NOTIFY_TYPE_DEL,
		})
		switch v {
		case limitedTimeEvent.EVENT_TYPE_HIGH_ROLLER:
			BaseMod := p.PlayMod.getBaseMod()
			EnergyMul := BaseMod.GetEnergyMul()
			OrderMod := p.PlayMod.getOrderMod()
			Emit := p.PlayMod.getChessMod().GetOrderEmit()
			ChessList := p.PlayMod.getChessMod().GetUnlockChessList()
			OrderMod.ChangeEnergyMul(Lv, Emit, EnergyMul, ChessList)
			p.PushClientRes(OrderMod.BackData())
			p.TeLog("mutil_merge_change", map[string]interface{}{
				"change_from": math.Pow(2, float64(EnergyMul)),
				"change_to":   math.Pow(2, float64(EnergyMul)),
				"is_auto":     true,
			})
			p.PushClientRes(p.PlayMod.getBaseMod().BackData())
		case limitedTimeEvent.EVENT_TYPE_SUPER_ORDER:
			p.PlayMod.getOrderMod().RemoveSuperOrder()
			p.PushClientRes(p.PlayMod.getOrderMod().BackData())
		case limitedTimeEvent.EVENT_TYPE_CARD_FESTIVAL:
			p.PlayMod.getCardMod().ResetCardFestival()
		case limitedTimeEvent.EVENT_TYPE_GOLDCARD_EX:
			p.PlayMod.getFriendMod().ResetGoldCardEx()
			p.LimitedTimeCardTrigger()
		}
	}

	for _, v := range AddEvent { // 增加事件处理
		switch v {
		case limitedTimeEvent.EVENT_TYPE_SUPER_ORDER:
			Emit := p.PlayMod.getChessMod().GetOrderEmit()
			Lv := p.GetPlayerBaseMod().GetLevel()
			EnergyMul := p.PlayMod.getBaseMod().GetEnergyMul()
			p.PlayMod.getOrderMod().CreateSuperOrder(Lv, Emit, EnergyMul)
			p.PushClientRes(p.PlayMod.getOrderMod().BackData())
		case limitedTimeEvent.EVENT_TYPE_CARD_FESTIVAL:
			p.PlayMod.getCardMod().CreateCardFestival()
		case limitedTimeEvent.EVENT_TYPE_CAT_DAY_SALE: // 猫咪大甩卖
			ChargeMod := p.PlayMod.getChargeMod()
			PlayroomMod := p.PlayMod.getPlayroomMod()
			if !ChargeMod.IsWeeklyDiscountDay() {
				ChargeMod.ResetWeeklyDiscount()
				PlayroomMod.ResetWeeklyDiscount()
			}

			p.ChargeBackData()
		}
	}
	p.PushClientRes(p.PlayMod.getLimitedTimeEventMod().BackData())
	p.PlayMod.save()
}

// 限时猪猪存钱罐触发器
func (p *Player) LimitedTimePiggyBankTrigger() {
	Remain := p.PlayMod.getPiggyBankMod().TimeOut()
	if Remain > 0 {
		p.CallEvent(time.Duration(Remain)*time.Second, func() {
			p.lock.Lock()
			defer p.lock.Unlock()
			p.LimitedTimePiggyBankTrigger()
			p.SendClientRes()
		}, "PiggyBank")
	}
	p.PushClientRes(p.PlayMod.getPiggyBankMod().BackData())
}

// 限时卡牌触发器
func (p *Player) LimitedTimeCardTrigger() {
	FriendMod := p.PlayMod.getFriendMod()
	CardMod := p.PlayMod.getCardMod()
	Now := GoUtil.Now()
	var EndTime int64
	for k, v := range FriendMod.Card {
		if v.EndTime > 0 && v.EndTime <= Now {
			switch v.Status {
			case card.STATUS_CARD_EX_1:
				delete(FriendMod.Card, k)
				FriendMgrSend(&MsgMod.Msg{
					From: v.BUid,
					To:   v.AUid,
					Type: MsgMod.HANDLE_TYPE_EX_CARD_SELECT_TIMEOUT,
				})
			case card.STATUS_CARD_EX_2:
				delete(FriendMod.Card, k)
				FriendMgrSend(&MsgMod.Msg{
					From: v.AUid,
					To:   v.BUid,
					Type: MsgMod.HANDLE_TYPE_EX_CARD_TIMEOUT,
				})
				p.AddCard(v.CardId)
				CardMod.DelExCard(v)
				p.PushClientRes(CardMod.NotifyTimes())
				p.PushClientRes(CardMod.NotifyCard())
			}
			continue
		}
		if v.EndTime > 0 && (EndTime == 0 || v.EndTime < EndTime) {
			EndTime = v.EndTime
		}
	}
	if EndTime > 0 {
		p.CallEvent(time.Duration(EndTime-Now)*time.Second, func() {
			p.lock.Lock()
			defer p.lock.Unlock()
			p.LimitedTimeCardTrigger()
			p.SendClientRes()
		}, "LimitedTimeCard")
	}
}
func (p *Player) LimitedTimePlayroomTrigger() {
	PlayroomMod := p.PlayMod.getPlayroomMod()
	for k, v := range PlayroomMod.Physiology {
		if v.Time > 0 {
			p.LimitedTimePlayroomTrigger_(k)
		}
	}
}

func (p *Player) LimitedTimePlayroomTrigger_(Id int) {
	PlayroomMod := p.PlayMod.getPlayroomMod()
	Physiology := PlayroomMod.GetPhysiology(Id)
	if Physiology == nil {
		return
	}
	NewTime, NextSecond, Num := PlayroomTrigger(Physiology.Id, Physiology.Time, Physiology.Num)
	Physiology.Time = NewTime
	DiffValue := Physiology.Num - Num
	MType, MEffect := playroomCfg.GetMoodEffect(Physiology.Id)
	CleanMood := PlayroomMod.GetMoodInfo(playroom.MOOD_TYPE_CLEAN)
	PlayroomMod.AddMood(MType, -MEffect*DiffValue)
	// 上厕所数值为0 且清洁度大于50时，清洁度降至50
	if Id == playroom.PHYSIOLOGY_TYPE_TOLIET && Num == 0 && CleanMood.Num > 50 {
		CleanMood.Num = 50
	}
	Physiology.Num = Num
	if PlayroomMod.GetMoodInfo(MType).Num == 0 { // 心情值为0时，重置生理状态
		PlayroomMod.ResetPhysiology(MType)
		NewTime = 0
	}
	p.PlayMod.save()
	ResNotifyMood := PlayroomMod.NotifyMood()
	p.PushClientRes(ResNotifyMood)
	if NextSecond > 0 {
		p.CallEvent(time.Duration(NextSecond)*time.Second, func() {
			p.lock.Lock()
			defer p.lock.Unlock()
			p.LimitedTimePlayroomTrigger_(Id)
			p.SendClientRes()
		}, fmt.Sprintf("Playroom_%d", Id))
	}
}

func PlayroomTrigger(Id int, Time int64, Num int) (int64, int64, int) {
	if Num == 0 {
		return 0, 0, 0
	}
	Now := GoUtil.Now()
	NeedDuration := playroomCfg.GetPhysiologyDuration(Id, Num)
	if Time+int64(NeedDuration) > Now {
		return Time, int64(NeedDuration), Num
	}
	n := 0
	for n <= 100 {
		Num--
		NeedDuration := playroomCfg.GetPhysiologyDuration(Id, Num)
		Time += int64(NeedDuration)
		if Time >= Now {
			return Now, int64(NeedDuration), Num
		}
		if Num == 0 {
			return 0, 0, 0
		}
		n++
	}
	return 0, 0, 0
}

func LimitedTimePlayroomWorkTrigger(p *Player) {
	PlayroomMod := p.PlayMod.getPlayroomMod()
	EndTime := PlayroomMod.Endtime
	Now := GoUtil.Now()
	if EndTime > 0 && EndTime <= Now {
		PlayroomMod.ResetWork()
		p.PlayMod.save()
		p.PlayroomBackData()
		p.SendClientRes()
		return
	}
	NextSecond := EndTime - Now
	if NextSecond > 0 {
		p.CallEvent(time.Duration(NextSecond)*time.Second, func() {
			p.lock.Lock()
			defer p.lock.Unlock()
			LimitedTimePlayroomWorkTrigger(p)
			p.SendClientRes()
		}, "PlayroomWork")
	}
}

func LimitedTimeEnergyAdd(p *Player) {
	curtime := time.Now().Unix()
	PlayerBaseMod := p.GetPlayerBaseMod()
	BaseMod := p.PlayMod.getBaseMod()
	delta := curtime - BaseMod.GetRecoverTime()
	Recover := userCfg.GetRecover(BaseMod.GetLevel())
	if Recover <= 0 {
		return
	}
	Addsta := int(delta) / Recover
	if Addsta <= 0 {
		return
	}
	Energy := BaseMod.GetEnergy()
	MaxEnergy := PlayerBaseMod.GetMaxEnergy()
	if MaxEnergy > Energy {
		E := MaxEnergy - Energy
		Energy += Addsta
		if Energy > MaxEnergy {
			Energy = MaxEnergy
		}
		p.TeLog("asset_change", map[string]interface{}{
			"item_id":       item.ITEM_ENERGY_ID,
			"change_type":   "gain",
			"change_num":    min(Addsta, E),
			"change_after":  Energy,
			"change_reason": "recover_server",
		})
		p.CallEvent(time.Duration(Recover)*time.Second, func() {
			p.lock.Lock()
			defer p.lock.Unlock()
			LimitedTimeEnergyAdd(p)
		}, "AddEnergy")
	}
	BaseMod.SetEnergy(Energy)
	BaseMod.SetRecoverTime(curtime)
	p.SendErrClienRes(PlayerBaseMod.BackAsset())
}

func GuideTaskTrigger(p *Player) {
	GuideTaskMod := p.PlayMod.getGuideTaskMod()
	UnlockTime := GuideTaskMod.UnlockTime
	if UnlockTime == 0 {
		return
	}
	Now := GoUtil.Now()
	NextSecond := 86400 - (Now-UnlockTime)%86400
	if NextSecond > 0 {
		p.CallEvent(time.Duration(NextSecond)*time.Second, func() {
			p.lock.Lock()
			defer p.lock.Unlock()
			GuideTaskMod.Login()
			p.PushClientRes(GuideTaskMod.BackData())
			p.SendClientRes()
		}, "PlayroomWork")
	}
}
