<?php

/**
 * 总熟练度
 */

namespace Game\Logic;

use Framework\Log\LogMark;
use Framework\MVC\ModelManager;
use Framework\Network\SendMessage;
use Framework\Logic\TemplateHelp;
use Game\Constant\ClientErrorCode;
use Game\Constant\ConstTemplate\TemplateConst;
use Game\Constant\ConstTemplate\TemplateProficiency;
use Game\Constant\ConstTemplate\TemplateTotalProficiency;
use Game\Constant\EventTypeDefine;
use Game\Constant\GameConstantDefine;
use Game\Constant\ModelTypeDefine;
use Game\Constant\TemplateDefine;
use Game\Data\Car\CarData;
use Game\Data\ProficiencyData;
use Game\Model\Car\CarModel;
use Game\Model\MoneyModel;
use Game\Model\ProficiencyModel;
use Game\Operation\EventLog\EventLog_Manager;
use Game\Operation\EventLog\EventLogType;
use Game\Protobuf\GCProficiencyData;
use Game\Protobuf\PacketId;

trait ProficiencyLogic
{
    use TemplateHelp;
    use ItemLogic;
    use MoneyLogic;
    use CarLogic;

    //获取总活跃度信息
    public function getTotalProficiencyData(): ProficiencyData
    {
        /**
         * @var ProficiencyModel $proficiencyModel
         */
        $proficiencyModel = ModelManager::getInstance()->getModel(ModelTypeDefine::PROFICIENCY_TOTAL);
        return $proficiencyModel->getTotalProficiencyData();
    }

    //更新总活跃度等级
    public function addTotalProficiencyLv(int $addLv)
    {
        $proficiencyData = $this->getTotalProficiencyData();
        $proficiencyData->proficiencyLv += $addLv;
        EventLog_Manager::getInstance()->updateUserAttr(array(EventLogType::LOG_KEY_PLAYER_PROFICIENCY_LV => $proficiencyData->proficiencyLv));
        //总熟练度
        $param = array(
            GameConstantDefine::EVENT_KEY_NUM => $addLv,
        );
        $this->triggerEvent(EventTypeDefine::EVENT_TYPE_TASK_TOTAL_PROFICIENCY, $param);
        $proficiencyData->updateDB();
    }

    //检查开启总活跃度高级奖励
    public function checkOpenTotalProficiencyExpertFlag(): int
    {
        $proficiencyData = $this->getTotalProficiencyData();
        if ($proficiencyData->proficiencyFlag) {
            return ClientErrorCode::PROFICIENCY_TOTAL_ALREADY_OPEN_EXPERT;
        }
        //检查钻石
        $needNum = $this->getTerm(
            TemplateDefine::TYPE_CONST,
            TemplateConst::Const_Buy_Proficiency_Flag,
            TemplateConst::ConstNum);
        if ($this->getMoney(MoneyModel::TYPE_DIAMOND) < $needNum) {
            return $this->getMoneyNotEnoughCode(MoneyModel::TYPE_DIAMOND);
        }
        return ClientErrorCode::CLIENT_SUCCESS;
    }

    //开启总活跃度高级奖励
    public function openTotalProficiencyExpertFlag(): ProficiencyData
    {
        $proficiencyData = $this->getTotalProficiencyData();
        $proficiencyData->proficiencyFlag = true;
        $proficiencyData->updateDB();
        return $proficiencyData;
    }

    //领取总活跃度单个奖励
    public function getTotalProficiencySingleReward(int $id, bool $isExpert, int &$code): ProficiencyData
    {
        $proficiencyData = $this->getTotalProficiencyData();
        //检查奖励是否存在
        $config = $this->getTitle(TemplateDefine::TYPE_PROFICIENCY_TOTAL, $id);
        if (is_null($config)) {
            $code = ClientErrorCode::PROFICIENCY_TOTAL_REWARD_NOT_FOUND;
            return $proficiencyData;
        }
        //检查等级
        if ($proficiencyData->proficiencyLv < $config[TemplateTotalProficiency::Level]) {
            $code = ClientErrorCode::PROFICIENCY_TOTAL_REWARD_LEVEL_NOT_ENOUGH;
            return $proficiencyData;
        }
        //检查是否开通高级
        if ($isExpert && !$proficiencyData->proficiencyFlag) {
            $code = ClientErrorCode::PROFICIENCY_TOTAL_REWARD_NOT_OPEN_EXPERT;
            return $proficiencyData;
        }
        //检查是否已领取
        if ($isExpert) {
            $proficiencyExpertReward = json_decode($proficiencyData->proficiencyExpertReward, true);
            if (in_array($id, $proficiencyExpertReward)) {
                $code = ClientErrorCode::PROFICIENCY_TOTAL_REWARD_ALREADY_GET;
                return $proficiencyData;
            }
            $reward = $config[TemplateTotalProficiency::ExpertReward];
            $proficiencyExpertReward[] = $id;
            sort($proficiencyExpertReward);
            $proficiencyData->proficiencyExpertReward = json_encode($proficiencyExpertReward);
        } else {
            $proficiencyReward = json_decode($proficiencyData->proficiencyReward, true);
            if (in_array($id, $proficiencyReward)) {
                $code = ClientErrorCode::PROFICIENCY_TOTAL_REWARD_ALREADY_GET;
                return $proficiencyData;
            }
            $reward = $config[TemplateTotalProficiency::Reward];
            $proficiencyReward[] = $id;
            sort($proficiencyReward);
            $proficiencyData->proficiencyReward = json_encode($proficiencyReward);
        }
        //发奖
        $this->addReward($reward);
        $proficiencyData->updateDB();
        $code = ClientErrorCode::CLIENT_SUCCESS;
        return $proficiencyData;
    }

    //一键领取总活跃度奖励
    public function getTotalProficiencyAllReward(): ProficiencyData
    {
        $proficiencyData = $this->getTotalProficiencyData();
        //检查奖励是否存在
        $totalConfig = $this->getTable(TemplateDefine::TYPE_PROFICIENCY_TOTAL);
        if (is_null($totalConfig)) {
            return $proficiencyData;
        }
        $allReward = array();
        $proficiencyExpertReward = json_decode($proficiencyData->proficiencyExpertReward, true);
        $proficiencyReward = json_decode($proficiencyData->proficiencyReward, true);
        //检查领取奖励
        foreach ($totalConfig as $id => $config) {
            if ($proficiencyData->proficiencyLv < $config[TemplateTotalProficiency::Level]) {
                break;
            }
            //普通奖励
            if (!in_array($id, $proficiencyReward)) {
                $proficiencyReward[] = $id;
                $this->tidyReward(
                    $config[TemplateTotalProficiency::Reward],
                    $allReward
                );
            }
            //高级奖励
            if ($proficiencyData->proficiencyFlag && !in_array($id, $proficiencyExpertReward)) {
                $proficiencyExpertReward[] = $id;
                $this->tidyReward(
                    $config[TemplateTotalProficiency::ExpertReward],
                    $allReward
                );
            }
        }
        //发奖
        $this->addReward($allReward);
        sort($proficiencyReward);
        sort($proficiencyExpertReward);
        $proficiencyData->proficiencyReward = json_encode($proficiencyReward);
        $proficiencyData->proficiencyExpertReward = json_encode($proficiencyExpertReward);
        $proficiencyData->updateDB();
        return $proficiencyData;
    }

    /**
     * 领取赛车单个熟练度奖励
     * @param int $carId
     * @param int $levelId  ProficientCar表 level
     * @param $code
     * @return array
     */
    public function getCarSingleProficiencyReward(int $carId, int $levelId, &$code): array
    {
        /**
         * @var carData $carData
         */
        $carData = $this->searchCarDataByCarID($carId);
        if (is_null($carData)) {
            $code = ClientErrorCode::PROFICIENCY_REWARD_CAR_NOT_FOUND;
            return [];
        }
        $proficiencyReward = json_decode($carData->proficiencyReward, true);
        //检查是否永久车
        if ($carData->expire != 0) {
            $code = ClientErrorCode::PROFICIENCY_REWARD_CAR_NOT_FOREVER;
            return $proficiencyReward;
        }
        //获取配置
        $carProficiencyConfig = $this->getTerm(TemplateDefine::TYPE_PROFICIENCY_CAR, $carId, $levelId);
        if (is_null($carProficiencyConfig)) {
            LogMark::getInstance()->markDebug(
                "[ProficiencyLogic] not found car Proficiency Config",
                array(
                    "carId" => $carId
                )
            );
            $code = ClientErrorCode::PROFICIENCY_REWARD_CAR_REWARD_NOT_FOUND;
            return $proficiencyReward;
        }
        if ($carData->proficiencyLv < $carProficiencyConfig[TemplateProficiency::Level]) {
            $code = ClientErrorCode::PROFICIENCY_REWARD_CAR_LEVEL_NOT_ENOUGH;
            return $proficiencyReward;
        }
        if (in_array($levelId, $proficiencyReward)) {
            $code = ClientErrorCode::PROFICIENCY_REWARD_CAR_ALREADY_GET;
            return $proficiencyReward;
        }
        //发奖
        $this->addReward($carProficiencyConfig[TemplateProficiency::Reward]);
        $proficiencyReward[] = $levelId;
        sort($proficiencyReward);
        $carData->setProficiencyReward(json_encode($proficiencyReward));
        $carData->saveDB();
        //通知car更新
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $carModel->addCarPacket($carData);
        $carModel->sendCarPacket();
        //成功
        $code = ClientErrorCode::CLIENT_SUCCESS;
        return $proficiencyReward;
    }

    //一键领取赛车熟练度奖励
    public function getCarAllProficiencyReward(int $carId, &$code): array
    {
        /**
         * @var carData $carData
         */
        $carData = $this->searchCarDataByCarID($carId);
        if (is_null($carData)) {
            $code = ClientErrorCode::PROFICIENCY_REWARD_CAR_NOT_FOUND;
            return [];
        }
        $proficiencyReward = json_decode($carData->proficiencyReward, true);
        //检查是否永久车
        if ($carData->expire != 0) {
            $code = ClientErrorCode::PROFICIENCY_REWARD_CAR_NOT_FOREVER;
            return $proficiencyReward;
        }
        //获取配置
        $carProficiencyConfig = $this->getTitle(TemplateDefine::TYPE_PROFICIENCY_CAR, $carId);
        if (is_null($carProficiencyConfig)) {
            LogMark::getInstance()->markDebug(
                "[ProficiencyLogic] not found car Proficiency Config",
                array(
                    "carId" => $carId
                )
            );
            $code = ClientErrorCode::PROFICIENCY_REWARD_CAR_REWARD_NOT_FOUND;
            return $proficiencyReward;
        }
        $allReward = array();
        foreach ($carProficiencyConfig as $levelId => $config) {
            if ($carData->proficiencyLv < $levelId) {
                break;
            }
            if (!in_array($levelId, $proficiencyReward)) {
                $this->tidyReward(
                    $config[TemplateProficiency::Reward],
                    $allReward
                );
                $proficiencyReward[] = $levelId;
            }
        }
        //发奖
        $this->addReward($allReward);
        sort($proficiencyReward);
        $carData->setProficiencyReward(json_encode($proficiencyReward));
        $carData->saveDB();
        //通知car更新
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $carModel->addCarPacket($carData);
        $carModel->sendCarPacket();
        //成功
        $code = ClientErrorCode::CLIENT_SUCCESS;
        return $proficiencyReward;
    }

    private function tidyReward(array $reward, array &$allReward)
    {
        foreach ($reward as $itemId => $num) {
            isset($allReward[$itemId]) ?
                $allReward[$itemId] += $num :
                $allReward[$itemId] = $num;
        }
    }

    //发奖
    private function addReward(array $reward)
    {
        $this->setLogAddItemSource(GameConstantDefine::ITEM_ADD_SOURCE_CAR_PROFICIENCY_REWARD);
        $this->gainItemArr($reward);
    }

    public function sendProficiencyDataMessage(ProficiencyData $data)
    {
        $sendMessage = new GCProficiencyData();
        $sendMessage->setProficiencyLv($data->proficiencyLv);
        $sendMessage->setProficiencyReward(json_decode($data->proficiencyReward, true));
        $sendMessage->setProficiencyExpertReward(json_decode($data->proficiencyExpertReward, true));
        $sendMessage->setProficiencyFlag($data->proficiencyFlag);
        SendMessage::getInstance()->sendClient(PacketId::GC_ProficiencyData, $sendMessage);
    }
}
