<?php

/**
 * 战令
 */

namespace Game\Model\Task;

use Framework\Log\LogMark;
use Framework\Network\SendMessage;
use Framework\DB\Handler\PlayerDBHandler;
use Framework\Logic\TemplateHelp;
use Game\Constant\ConstTemplate\TemplateConst;
use Game\Constant\ConstTemplate\TemplateZLReward;
use Game\Constant\DBTableDefine;
use Game\Constant\GameConstantDefine;
use Game\Constant\GameErrorCode;
use Game\Constant\ModelTypeDefine;
use Game\Constant\TemplateDefine;
use Game\Data\WarTokenData;
use Game\Logic\CommonConstLogic;
use Game\Protobuf\GCZLInfo;
use Game\Protobuf\PacketId;
use Game\Logic\ItemLogic;

class WarTokenModel
{
    use TemplateHelp;
    use PlayerDBHandler;
    use CommonConstLogic;
    use ItemLogic;

    private int $playerId;
    private ?WarTokenData $warTokenData = null;
    private ?array $rewardConfig = null;
    private GCZLInfo $sendMessage;
    public array $primaryIdList = array();
    public array $expertIdList = array();

    public function setPlayerId($playerId)
    {
        $this->playerId = $playerId;
    }

    public function __construct()
    {
        $this->sendMessage = new GCZLInfo();
    }


    //重置战令信息
    public function reset()
    {
        $this->init();
        $this->warTokenData->initWarToken();
        $this->warTokenData->updateDB();
    }

    public function resetWeekExp()
    {
        $this->init();
        $this->warTokenData->weekExp = 0;
        $this->warTokenData->updateDB();
    }

    //获取战令信息
    public function getWarTokenData(): WarTokenData
    {
        $this->init();
        return $this->warTokenData;
    }

    //加战令经验
    public function addWarTokenExp(int $addExp)
    {
        $this->init();
        // 最大经验值
        $maxExp = (int)$this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_ZL_Max_Exp,
            TemplateConst::ConstNum);
        // 溢出上限
        $maxOverFlow = (int)$this->getTerm(TemplateDefine::TYPE_CONST,
            TemplateConst::Const_ZL_OutFlow_Exp, TemplateConst::ConstNum);

        $num = 0;
        if ($this->warTokenData->overMaxFlag) {
            $val = $this->warTokenData->overFlowExp + $addExp;
            // 需要领取礼包的次数
            $num = intdiv($val, $maxOverFlow);
            $extra = $val % $maxOverFlow;
            $this->warTokenData->overFlowExp = $extra;
        } else {
            $this->warTokenData->warTokenExp += $addExp;
            if ($this->warTokenData->warTokenExp >= $maxExp) {
                $val = $this->warTokenData->warTokenExp - $maxExp;
                $num = intdiv($val, $maxOverFlow);
                $extra = $val % $maxOverFlow;
                $this->warTokenData->overFlowExp = $extra;
                $this->warTokenData->overMaxFlag = WarTokenData::OVER_MAX_FLAG_OPEN;
                $this->warTokenData->warTokenExp = $maxExp;
            }
        }
        if($num != 0) {
            // 溢出获得道具
            $itemID = (int)$this->getTerm(TemplateDefine::TYPE_CONST,
                TemplateConst::Const_ZL_OutFlow_Item, TemplateConst::ConstNum);
            $itemCfg = $this->getTitle(TemplateDefine::TYPE_ITEM, $itemID);
            $this->useItemOpenGift($itemCfg, $num);
        }
        $this->warTokenData->updateDB();
    }

    //加战令周经验
    public function addWarTokenWeekExp(int $addExp)
    {
        $this->init();
        $maxWeekExp = (int)$this->getTerm(
            TemplateDefine::TYPE_CONST,
            TemplateConst::Const_War_Token_Week_Max_Exp,
            TemplateConst::ConstNum);
        if ($this->warTokenData->weekExp >= $maxWeekExp) {
            return;
        }
        if ($this->warTokenData->weekExp + $addExp >= $maxWeekExp) {
            $addExp = $maxWeekExp - $this->warTokenData->weekExp;
            $this->warTokenData->weekExp = $maxWeekExp;
        } else {
            $this->warTokenData->weekExp += $addExp;
        }
        $this->addWarTokenExp($addExp);
    }

    //初级奖励 已领取id
    public function getPrimaryIdList(): array
    {
        $this->init();
        return $this->primaryIdList;
    }

    //高级奖励想 已领取id
    public function getExpertIdList(): array
    {
        $this->init();
        return $this->expertIdList;
    }

    //获取战令可领取等级
    public function getWarTokenCanLv(int $addExp = 0): int
    {
        $this->init();
        $exp = $this->warTokenData->warTokenExp;
        $exp += $addExp;
        $levelExp = $this->getTerm(TemplateDefine::TYPE_CONST,
                                                TemplateConst::Const_Task_ZL_Level_Exp,
                                                TemplateConst::ConstNum);
        if (is_null($levelExp)) {
            LogMark::getInstance()->markWarn(
                GameErrorCode::TEMPLATE_ID_NOT_FOUND,
                "[WarTokenModel] const table not found",
                array(
                    "TemplateTable" => TemplateDefine::TYPE_CONST,
                    "id" => TemplateConst::Const_Task_ZL_Level_Exp,
                )
            );
            return 0;
        }
        $lv = (int)($exp / $levelExp);
        //检查最高级
        $maxLv = $this->getRewardMaxLv();
        return $lv <= $maxLv ? $lv : $maxLv;
    }

    //获取奖励最大值
    private function getRewardMaxLv(): int
    {
        $this->getWarTokenRewardConfig();
        return count($this->rewardConfig);
    }

    //领取初级奖励
    public function getPrimaryReward(int $lv, array &$reward)
    {
        if (in_array($lv, $this->primaryIdList)) {
            return;
        }
        $tmpReward = $this->getConfigReward($lv);
        foreach ($tmpReward as $itemId => $num) {
            isset($reward[$itemId]) ? $reward[$itemId] += $num : $reward[$itemId] = $num;
        }
        $this->primaryIdList[] = $lv;
    }

    //领取高级奖励
    public function getExpertReward(int $lv, array &$reward, int $option)
    {
        if (in_array($lv, $this->expertIdList)) {
            return;
        }
        $tmpReward = $this->getConfigReward($lv, $option);
        foreach ($tmpReward as $itemId => $num) {
            isset($reward[$itemId]) ? $reward[$itemId] += $num : $reward[$itemId] = $num;
        }
        $this->expertIdList[] = $lv;
    }

    public function saveWarTokenData()
    {
        sort($this->primaryIdList);
        sort($this->expertIdList);
        $this->warTokenData->primaryIds = json_encode($this->primaryIdList);
        $this->warTokenData->expertIds = json_encode($this->expertIdList);
        $this->warTokenData->updateDB();
    }

    //检查战令奖励id是否存在
    public function checkRewardIsExist(int $id, int $option): bool
    {
        $this->getWarTokenRewardConfig();
        $ret = $this->getConfigReward($id, $option);
        return !empty($ret);
    }

    //获取配置奖励
    private function getConfigReward(int $lv, int $option = 0): array
    {
        if (!isset($this->rewardConfig[$lv])) {
            return array();
        }
        $config = $this->rewardConfig[$lv];
        switch($option) {
            case 0:
                return $config[TemplateZLReward::Primary];
            case 1:
                return $config[TemplateZLReward::Expert];
            case 2:
                return $config[TemplateZLReward::Elite];

        }
        return [];
    }

    //获取奖励配置
    private function getWarTokenRewardConfig()
    {
        if (is_null($this->rewardConfig)) {
            $config = $this->getTable(TemplateDefine::TYPE_ZL_REWARD);
            if (is_null($config)) {
                LogMark::getInstance()->markWarn(
                    GameErrorCode::TEMPLATE_ID_NOT_FOUND,
                    "[WarTokenModel] ScheduleReward table not found",
                    array(
                        "TemplateTable" => TemplateDefine::TYPE_ZL_REWARD,
                    )
                );
                $this->rewardConfig = array();
            } else {
                $this->rewardConfig = $config;
            }
        }
    }

    private function init()
    {
        if (is_null($this->warTokenData)) {
            $this->warTokenData = new WarTokenData($this->playerId);
            if (false == $this->warTokenData->searchDB()) {
                $this->warTokenData->initWarToken();
                $this->warTokenData->createDB();
            }
            $this->primaryIdList = json_decode($this->warTokenData->primaryIds, true);
            $this->expertIdList = json_decode($this->warTokenData->expertIds, true);
        }
    }

    public function sendMessage()
    {
        $this->init();
        $this->sendMessage->setExp($this->warTokenData->warTokenExp);
        $this->sendMessage->setExpertFlag($this->warTokenData->expertFlag);
        $this->sendMessage->setPrimaryId($this->primaryIdList);
        $this->sendMessage->setExpertId($this->expertIdList);
        $this->sendMessage->setOverFlowExp($this->warTokenData->overFlowExp);
        $result = $this->getCommonConstData();
        $this->sendMessage->setWeek($result[GameConstantDefine::COMMON_KEY_SEASON_WEEK]);
        $this->sendMessage->setWeekExp($this->warTokenData->weekExp);
        SendMessage::getInstance()->sendClient(PacketId::GC_ZLInfo, $this->sendMessage);
    }

    //重置玩家模块索引   战令任务model->0
    public function resetSeasonWeek()
    {
        $this->updateTitle(
            DBTableDefine::TABLE_ACCOUNT,
            $this->playerId,
            0,
            array(
                ModelTypeDefine::TASK_SEASON => 0
            )
        );
    }
}
