package main

import (
	"time"

	"mongo.games.com/goserver/core/logger"
	"mongo.games.com/goserver/core/netlib"

	"mongo.games.com/game/common"
	taskproto "mongo.games.com/game/protocol/task"
	"mongo.games.com/game/srvdata"
)

const (
	TaskStateFinish = 1 // 任务完成
	TaskStateReward = 2 // 任务奖励已领取
)

func init() {
	// 获取任务列表
	common.Register(int(taskproto.TaskPacketID_PACKET_CSTaskList), taskproto.CSTaskList{}, CSTaskList)
	// 领取任务奖励
	common.Register(int(taskproto.TaskPacketID_PACKET_CSTaskReward), taskproto.CSTaskReward{}, CSTaskReward)
	//  测试用：直接增加任务计数
	common.Register(int(taskproto.TaskPacketID_PACKET_CSDebugInc), taskproto.CSTaskDebugInc{}, CSTaskDebugInc)
}

// GetTaskTimes 获取任务完成进度
func GetTaskTimes(p *Player, id int32) int64 {
	if p.WelfData != nil && p.WelfData.Task[id] != nil {
		return p.WelfData.Task[id].N
	}
	return 0
}

// IsTaskFinish 是否任务完成
func IsTaskFinish(p *Player, id int32) bool {
	data := srvdata.PBDB_TaskMgr.GetData(id)
	if data == nil {
		return false
	}
	if p.WelfData != nil && p.WelfData.Task[id] != nil {
		return p.WelfData.Task[id].N >= data.GetTargetTimes()
	}
	return false
}

// IsTaskReward 是否任务奖励已领取
func IsTaskReward(p *Player, id int32) bool {
	if p.WelfData != nil && p.WelfData.Task != nil {
		if data := p.WelfData.Task[id]; data != nil && data.Ts > 0 {
			t := srvdata.PBDB_TaskMgr.GetData(id)
			switch t.ActivityType {
			case common.TaskActivityTypeEveryDay:
				if common.TsInSameDay(time.Now().Unix(), data.Ts) {
					return true
				}

			case common.TaskActivityTypeWeek:
				if common.TsInSameWeek(time.Now().Unix(), data.Ts) {
					return true
				}

			case common.TaskActivityTypeNovice, common.TaskActivityTypeInvite:
				if data.Ts > 0 {
					return true
				}
			}
		}
	}
	return false
}

func SendReward(p *Player, m map[int64]int64) {
	var items []*Item
	for k, v := range m {
		items = append(items, &Item{
			ItemId:  int32(k),
			ItemNum: v,
		})
	}
	BagMgrSingleton.AddJybBagInfo(p, items, 0, common.GainWay_TaskReward, "system", "任务奖励")
	for _, v := range items {
		data := srvdata.PBDB_GameItemMgr.GetData(v.ItemId)
		if data != nil {
			BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemObtain, v.ItemId, data.Name, v.ItemNum, "任务获得")
		}
	}
}

func CSTaskList(s *netlib.Session, packetId int, data interface{}, sid int64) error {
	logger.Logger.Tracef("CSTaskList %v", data)
	msg, ok := data.(*taskproto.CSTaskList)
	if !ok {
		return nil
	}
	p := PlayerMgrSington.GetPlayer(sid)
	if p == nil {
		return nil
	}

	ret := &taskproto.SCTaskList{
		Tp: msg.GetTp(),
	}

	// todo 优化
	tp := msg.GetTp()
	for _, v := range srvdata.PBDB_TaskMgr.Datas.GetArr() {
		if v.GetActivityType() != tp {
			continue
		}
		item := &taskproto.TaskData{
			Id:       v.Id,
			N:        GetTaskTimes(p, v.Id),
			TargetN:  v.GetTargetTimes(),
			Status:   0,
			Reward:   v.GetAward(),
			TaskType: v.GetTaskType(),
		}
		if item.N > item.TargetN {
			item.N = item.TargetN
		}
		if IsTaskReward(p, v.Id) {
			item.Status = TaskStateReward
		} else if IsTaskFinish(p, v.Id) {
			item.Status = TaskStateFinish
		}
		ret.List = append(ret.List, item)
	}
	p.SendToClient(int(taskproto.TaskPacketID_PACKET_SCTaskList), ret)
	logger.Logger.Tracef("SCTaskList %v", ret)
	return nil
}

func CSTaskReward(s *netlib.Session, packetId int, data interface{}, sid int64) error {
	logger.Logger.Tracef("CSTaskReward %v", data)
	msg, ok := data.(*taskproto.CSTaskReward)
	if !ok {
		return nil
	}
	p := PlayerMgrSington.GetPlayer(sid)
	if p == nil {
		return nil
	}

	ret := &taskproto.SCTaskReward{
		OpCode: taskproto.OpResultCode_OPRC_Error,
		Tp:     msg.GetTp(),
		Id:     msg.GetId(),
	}

	if IsTaskFinish(p, msg.GetId()) && !IsTaskReward(p, msg.GetId()) {
		p.WelfData.Task[msg.GetId()].Ts = time.Now().Unix()
		data := srvdata.PBDB_TaskMgr.GetData(msg.GetId())
		if data != nil {
			SendReward(p, data.Award)
		}
		ret.OpCode = taskproto.OpResultCode_OPRC_Success
	}

	p.SendToClient(int(taskproto.TaskPacketID_PACKET_SCTaskReward), ret)
	logger.Logger.Tracef("SCTaskReward %v", ret)
	return nil
}

func CSTaskDebugInc(s *netlib.Session, packetId int, data interface{}, sid int64) error {
	if !common.Config.IsDevMode {
		return nil
	}

	logger.Logger.Tracef("CSTaskDebugInc %v", data)
	msg, ok := data.(*taskproto.CSTaskDebugInc)
	if !ok {
		return nil
	}
	p := PlayerMgrSington.GetPlayer(sid)
	if p == nil {
		return nil
	}

	id := msg.GetId()
	taskType := int32(-1)
	for _, v := range srvdata.PBDB_TaskMgr.Datas.GetArr() {
		if v.Id == id {
			taskType = v.TaskType
			break
		}
	}

	p.ResetTaskN(taskType)
	TaskSubjectSingleton.Touch(int(taskType), &TaskData{
		SnId:  p.SnId,
		Num:   int64(msg.GetAddNum()),
		Debug: true,
	})

	ret := &taskproto.SCTaskDebugInc{
		OpCode: taskproto.OpResultCode_OPRC_Success,
	}
	p.SendToClient(int(taskproto.TaskPacketID_PACKET_SCDebugInc), ret)
	logger.Logger.Tracef("CSTaskDebugInc %v", ret)
	return nil
}
