package dailyTask

import (
	"fmt"
	dailyTaskCfg "server/conf/daily_task"
	"server/game/mod/item"
	"server/game/mod/quest"
	GoUtil "server/game_util"
	"server/msg"
	"server/pkg/github.com/name5566/leaf/log"
	"sort"
)

type DailyTaskMod struct {
	WeekReward map[int]WeekReward
	DayTask    map[int]DailyTask
	lastTask   map[int]struct{}
	Active     int
	Lock       bool
}

type WeekReward struct {
	Items  []*item.Item
	Id     int
	Status bool
}

type DailyTask struct {
	Items  []*item.Item
	Status int
	Quest  quest.QuestProgress
	UnLock bool
}

func (dt *DailyTaskMod) InitData() {
	if dt.WeekReward == nil {
		dt.WeekReward = make(map[int]WeekReward)
	}
	if dt.DayTask == nil {
		dt.DayTask = make(map[int]DailyTask)
	}
	if dt.lastTask == nil {
		dt.lastTask = make(map[int]struct{})
	}
}

func (dt *DailyTaskMod) Unlock() {
	dt.Lock = true
}

func (dt *DailyTaskMod) LevUpTrigger(Lv, AreaId int) bool {
	if len(dt.DayTask) != 0 {
		return false
	}
	dt.ZeroUpdate(Lv, AreaId)
	return true
}

func (dt *DailyTaskMod) ZeroUpdate(Lv, AreaId int) {
	TaskList := dailyTaskCfg.GetTaskList(Lv)
	if len(TaskList) <= 0 {
		return
	}
	TaskListId := GoUtil.GetMapKey(TaskList)
	LastTaskId := GoUtil.GetMapKey(dt.lastTask)
	TaskList1 := GoUtil.SubSlices(TaskListId, LastTaskId)
	TaskId := GoUtil.RandSliceNum(TaskList1, 3)
	for i := 0; i < len(TaskId); i++ {
		Id := i + 1
		questStr := TaskList[TaskId[i]]
		QuestProgress, err := quest.ParseQuest(questStr)
		if err != nil {
			log.Debug("parse quest err str : %s", questStr)
		}
		Items := getTaskReward(Id, AreaId)
		dt.DayTask[Id] = DailyTask{
			Items:  Items,
			UnLock: Id == 1,
			Quest:  QuestProgress,
		}
	}
	// 更新 lastTask，下次不重复当前任务
	dt.lastTask = make(map[int]struct{}, len(TaskId))
	for _, id := range TaskId {
		dt.lastTask[id] = struct{}{}
	}
}

func (dt *DailyTaskMod) WeekUpdate() {
	jackpot := dailyTaskCfg.GetTaskWeekJackpot()
	jackpotRand := randJackpot(jackpot, 5)
	jackpotId := GoUtil.GetMapKey(jackpotRand)
	sort.Ints(jackpotId)
	weekReward := make(map[int]WeekReward, len(jackpotId)+1)
	for i, v := range jackpotId {
		weekReward[i+1] = WeekReward{
			Id:    v,
			Items: jackpotRand[v],
		}
	}
	weekReward[6] = WeekReward{
		Id:    0,
		Items: []*item.Item{{Id: item.ITEM_FIVE_STAR_CARD_PACK, Num: 1}},
	}
	dt.Active = 0
	dt.WeekReward = weekReward
}

func (dt *DailyTaskMod) Trigger(Tr *quest.Trigger) bool {
	if !dt.Lock {
		return false
	}
	update := false
	for k, v := range dt.DayTask {
		if !v.UnLock {
			continue
		}
		if v.Status != quest.QUEST_STATUS_UNFINISH {
			continue
		}
		up := quest.TriggerQuestProgress(&v.Quest, Tr)
		if up {
			update = true
		}
		if v.Quest.Status {
			v.Status = quest.QUEST_STATUS_FINISH
			if _, ok := dt.DayTask[k+1]; ok {
				task := dt.DayTask[k+1]
				task.UnLock = true
				dt.DayTask[k+1] = task
			}
		}
		dt.DayTask[k] = v
	}
	return update
}

func (dt *DailyTaskMod) BackData() *msg.ResDailyTask {
	WeekReward := make(map[int32]*msg.DailyWeek)
	DailyTask := make(map[int32]*msg.DailyTask)
	for k, v := range dt.WeekReward {
		NeedActive := dailyTaskCfg.GetTaskActiveById(k)
		WeekReward[int32(k)] = &msg.DailyWeek{
			Status:     v.Status,
			NeedActive: int32(NeedActive),
			Items:      item.ItemToMsg(v.Items),
		}
	}
	for k, v := range dt.DayTask {
		DailyTask[int32(k)] = &msg.DailyTask{
			Status:   int32(v.Status),
			UnLock:   v.UnLock,
			Progress: quest.QuestProgressToMsg(&v.Quest),
			Items:    item.ItemToMsg(v.Items),
		}
	}
	DayEnd := GoUtil.NextZeroTimestampDuration()
	WeekEnd := GoUtil.NextWeekTimestampDuration()
	return &msg.ResDailyTask{
		WeekReward: WeekReward,
		DailyTask:  DailyTask,
		Active:     int32(dt.Active),
		DayEnd:     int32(DayEnd),
		WeekEnd:    int32(WeekEnd),
	}
}

func (dt *DailyTaskMod) GetDailyReward(id int) ([]*item.Item, error) {
	if v, ok := dt.DayTask[id]; ok {
		if v.Status == quest.QUEST_STATUS_FINISH {
			v.Status = quest.QUEST_STATUS_REWARD
			dt.DayTask[id] = v
			dt.Active += 5
			return v.Items, nil
		}
	}
	return nil, fmt.Errorf("task not finish")
}

func (dt *DailyTaskMod) GetWeekReward(id int) ([]*item.Item, error) {
	if v, ok := dt.WeekReward[id]; ok {
		NeedActive := dailyTaskCfg.GetTaskActiveById(id)
		if dt.Active < NeedActive {
			return nil, fmt.Errorf("active not enough")
		}
		if !v.Status {
			v.Status = true
			dt.WeekReward[id] = v
			return v.Items, nil
		}
	}
	return nil, fmt.Errorf("task not finish")
}

func (dt *DailyTaskMod) GetWeekReward2() []*item.Item {
	maxId := 0
	for id := range dt.WeekReward {
		if id > maxId {
			maxId = id
		}
	}
	if v, ok := dt.WeekReward[maxId]; ok {
		NeedActive := dailyTaskCfg.GetTaskActiveById(maxId)
		if dt.Active < NeedActive {
			return nil
		}
		if !v.Status {
			return v.Items
		}
	}
	return nil
}
