<?php

/**
 * CarLogic.php
 * 赛车
 */

namespace Game\Logic;

use Framework\Define\ErrorDefine;
use Framework\Lib\Utils;
use Framework\Log\LogMark;
use Framework\MVC\ModelManager;
use Framework\Network\SendMessage;
use Framework\Logic\TemplateHelp;
use Game\Constant\ClientErrorCode;
use Game\Constant\ConstTemplate\TemplateCar;
use Game\Constant\ConstTemplate\TemplateCarAggrandizement;
use Game\Constant\ConstTemplate\TemplateCarDeepmod;
use Game\Constant\ConstTemplate\TemplateCompetitionMode;
use Game\Constant\ConstTemplate\TemplateConst;
use Game\Constant\ConstTemplate\TemplateItem;
use Game\Constant\EventTypeDefine;
use Game\Constant\GameConstantDefine;
use Game\Constant\GameErrorCode;
use Game\Constant\ModelTypeDefine;
use Game\Data\AccountData;
use Game\Data\Car\CarNoticeData;
use Game\Data\Car\CarDeepmodData;
use Game\Logic\Task\BranchTaskLogic;
use Game\Method\Player\PlayerBuffLogic;
use Game\Model\AccountModel;
use Game\Model\Car\CarModel;
use Game\Constant\TemplateDefine;
use Game\Data\Car\CarData;
use Game\Operation\EventLog\CarUpdateLog;
use Game\Operation\EventLog\EventLog_Manager;
use Game\Operation\EventLog\EventLogType;
use Game\Protobuf\CarDataSingle;
use Game\Protobuf\GCNewCarNotice;
use Game\Protobuf\PacketId;
use Game\Model\Rank\RankModel;

trait CarLogic {
    use TemplateHelp;
    use EventLogic;
    use BranchTaskLogic;
    use EventConditionLogic;
    use PlayerBuffLogic;
    use ItemLogic;

    /**
     * 系统创建未拥有赛车
     * @param int $carID
     * @param int $level
     * @param int $expire 0 永久 unixTime为指定时间
     * @return bool
     */
    public function systemGainCar(int $carID, int $level, int $expire):bool {
        if(!$this->createCar($carID, $level, $expire)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                '[CarLogic] system create car error!',
                ['carID'=>$carID]
            );
            return false;
        }
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $carModel->sendCarPacket();
        //新车通知--临时用
        $this->addNewCarNotice($carID, $carModel->playerId);
        $this->sendNewCarNotice($carModel->playerId);
        return true;
    }

    public function gmItemGainCar(int $carID, int $level = 1, int $expire = 0, int $itemID = 0, int $num = 1): bool {
        if(!$this->itemGainCarLogic($carID, $level, $expire, $itemID, $num)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                '[CarLogic] gm gain car error!',
                ['carID' => $carID, 'expire' => $expire, 'itemID' => $itemID]
            );
            return false;
        }
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $carModel->addCarExec();
        //新车通知--临时用
        $this->addNewCarNotice($carID, $carModel->playerId);
        $this->sendNewCarNotice($carModel->playerId, true);
        return true;
    }

    /**
     * desc 道具获得赛车
     * @param int $carID
     * @param int $level     等级 默认为 1
     * @param int $expire    失效时间 默认为0 永久  非永久此处填写时间长度
     * @param int $itemID    折算车依据表
     * @return bool
     */
    public function itemGainCar(int $carID, int $level = 1, int $expire = 0, int $itemID = 0): bool {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);

        if(!$this->itemGainCarLogic($carID, $level, $expire, $itemID)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                '[CarLogic] item gain car error!',
                ['carID'=>$carID]
            );
            return false;
        }

        $carModel->sendCarPacket();
        //新车通知--临时用
        $this->addNewCarNotice($carID, $carModel->playerId);
        $this->sendNewCarNotice($carModel->playerId);
        return true;
    }

    public function itemGainCarLogic(int $carID, int $level = 1, int $expire = 0, int $itemID = 0, int $num = 1): bool {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);

        $carCfg = $this->getTitle(TemplateDefine::TYPE_CAR, $carID);
        if($carCfg[TemplateCar::Open] != CarModel::IS_OPEN) {
            LogMark::getInstance()->setLastErrorID(GameErrorCode::CREATE_CAR_BUG_NOT_OPEN);
            LogMark::getInstance()->markError(
                GameErrorCode::CREATE_CAR_BUG_NOT_OPEN,
                '[CarLogic] gain car logic but not open!',
                ['carID'=>$carID]
            );
            return false;
        }

        $car = $carModel->searchCarByCarID($carID);

        $carTime = $this->getCarExpireTime($expire);
        if(is_null($car)) {

            if(!$this->createCar($carID, $level, $carTime, $itemID)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_CREATE_ERROR,
                    '[CarLogic] logic create car is error!',
                    (array)$car
                );
                return false;
            }
            if($num <= 1) {
                return true;
            }
            $this->itemGainCarLogic($carID, $level, $expire, $itemID , $num-1);
            return true;
        }

        if(!$this->checkCarStateIsNormal($car)) {
            if(!$carModel->changeState($car, CarModel::STATE_NORMAL)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_UPDATE_ERROR,
                    '[CarLogic] car logic change state error!', (array)$car
                );
                return false;
            }
            if(!$carModel->changeExpire($car, $carTime)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_UPDATE_ERROR,
                    '[CarLogic] car logic change Expire error!',
                    (array)$car
                );
                return false;
            }
            if($num > 1) {
                $this->itemGainCarLogic($carID, $level, $expire, $itemID , $num-1);
            }
            //临时车转永久车,计算熟练度
            $this->addCarProficiency($carID, 0);
        }

        if(!$this->exchangeCar($car, $carTime, $itemID, $num)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarLogic] car logic gain save error!',
                (array)$car
            );
            return false;

        }
        return true;
    }

    // 强化赛车
    public function upGrade(int $uid, int $tpl1, int $num1, int $tpl2, int $num2): int {
        $this->setLogConsumeItemSource(GameConstantDefine::ITEM_CONSUME_SOURCE_CAR_LV_UP);
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $car = $carModel->searchCarByUid($uid);
        if(is_null($car)) {
            LogMark::getInstance()->markError(
                GameErrorCode::CAR_DATA_GET_FAILED,
                '[CarLogic] car upGrade search car obj by carID error!',
                ['uid'=>$uid]
            );
            return ClientErrorCode::ERROR_CAR_NOT_EXIST;
        }

        // 升级后模板信息
        $carCfg = $this->getTitle(
            TemplateDefine::TYPE_CAR_AGGRANDIZEMENT,
            $this->getCarAggrandizementID($car->carID, $car->level+1)
        );

        // 检测是否是最高等级
        if(!$this->checkLevelIsMax($car)) {
            return ClientErrorCode::ERROR_CAR_LEVEL_IS_MAX;
        }

        // TODO: 检测道具是否充足 包含万能碎片处理
        $consumeItem = $carCfg[TemplateCarAggrandizement::BoostItemConsumption];
        $consumeItem[$tpl1] = $num1;
        if(!empty($tpl2)) {
            $consumeItem[$tpl2] = $num2;
        }
        if(!$this->checkNumCanEnough($consumeItem, $carModel::ITEM)) {
            return ClientErrorCode::ERROR_CAR_UPGRADE_ITEM_NOT_ENOUGH;
        }

        // 消耗道具
        if(!$this->upGradeConsume($consumeItem, $carModel::ITEM)) {
            return ClientErrorCode::ERROR_CAR_UPGRADE_CONSUME_ITEM;
        }

        // 检测货币是否充足
        if(!$this->checkNumCanEnough($carCfg[TemplateCarAggrandizement::BoostCurrencyConsumption],
            $carModel::MONEY)) {
            return ClientErrorCode::ERROR_CAR_UPGRADE_MONEY_NOT_ENOUGH;
        }

        // 消耗货币
        if(!$this->upGradeConsume($carCfg[TemplateCarAggrandizement::BoostCurrencyConsumption], $carModel::MONEY)) {
            return ClientErrorCode::ERROR_CAR_UPGRADE_CONSUME_MONEY;
        }

        // 升级车辆
        if(!$carModel->changeLevel($car, $car->level + 1)) {
            return ClientErrorCode::ERROR_CAR_UPGRADE;
        }

        // 修改性能分
        if(!$carModel->changePerformance($car, $carCfg[TemplateCarAggrandizement::Performance])) {
            return ClientErrorCode::ERROR_CAR_UPGRADE;
        }

        // 获取奖励道具
        if(!$this->upGradeReward($carCfg[TemplateCarAggrandizement::BounsItems])) {
            return ClientErrorCode::ERROR_CAR_UPGRADE_REWARD;
        }

        $carModel->sendCarPacket();
        //触发任务
        $eventData = array(
            GameConstantDefine::EVENT_KEY_NUM => 1,
            GameConstantDefine::EVENT_KEY_CAR_ID => $car->carID,
            GameConstantDefine::EVENT_KEY_NEW_CAR => false,
        );
        $this->triggerEvent(EventTypeDefine::EVENT_TYPE_TASK_CAR_GARDE, $eventData);
        //记录打点日志
        $log = EventLog_Manager::getInstance()->getEventLog(EventLogType::Car);
        if (!is_null($log)) {
            /**
             * @var CarUpdateLog $log
             */
            $log->carId = $car->carID;
            $log->updateType = 1;
            $log->carLv = $car->level;
            $log->carProficiencyLv = $car->proficiencyLv;
            $log->carPerformance = $car->proficiency;
            $log->carEquip = json_encode($carModel->getCarExteriorItemIds($car->uid));
            $log->markLog();
        }
        return ClientErrorCode::CLIENT_SUCCESS;
    }

    private function getCarExpireTime($expire): int {
        $time = 0;
        if($expire != CarModel::CAR_EXPIRE_NORMAL) {
            $time = Utils::getServerTimestamp() + $expire;
        }
        return $time;
    }

    private function checkCarStateIsNormal(CarData $car):bool {
        return $car->state == CarModel::STATE_NORMAL;
    }

    private function createCar(int $carID, int $level, int $expire, int $itemID = 0):bool {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        // 判断是否拥有
        if(!is_null($carModel->searchCarByCarID($carID))) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                '[CarLogic] car is exists create error!',
                ['carID'=>$carID, 'expire'=>$expire]
            );
            return false;
        }
        if(!$carModel->createCar($carID, $level, $expire)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                '[CarLogic] car create error!',
                ['carID'=>$carID, 'expire'=>$expire]
            );
            return false;
        }

        // 创建赛车技能
        if(!$this->initSkillData($carID, $level)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                '[CarLogic] car skill create error!',
                ['carID'=>$carID, 'expire'=>$expire]
            );
            return false;
        }

        //创建支线任务
        $this->createBranchTask($carID);

        // TODO:: after add other module init data is here

        $this->addCarRefitRank($expire,$itemID, TemplateItem::TYPE_CAR);

        return true;
    }

    /*
     * @param type 1 车辆 2 车辆改装件
     */
    public function addCarRefitRank(int $expire, int $itemID, int $type): bool {
        // 限时车改装件不增加分数
        if(!empty($expire)) {
            return true;
        }
        /**
         * @var RankModel $rankModel
         */
        $rankModel = ModelManager::getInstance()->getModel(ModelTypeDefine::RANKING);

        $rankType = RankModel::CAR_REFIT;

        if(empty($itemID)) {
            return true;
        }
        $itemCfg = $this->getTitle(TemplateDefine::TYPE_ITEM, $itemID);
        $score = $itemCfg[TemplateItem::ScoreNum];
        if($score === 0) {
            return true;
        }
        $newScore = $this->changeRankingEventPooled($rankType, $score);

        if(!$rankModel->changeRankScore($rankType, $newScore)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[item logic] update rank data [item car] error!',
                ['rankType' => $rankType, 'now score' => $score]
            );
        }
        return true;
    }

    // 折算赛车
    private function exchangeCar(CarData $car, int $expire, int $itemID, int $num = 0): bool {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);

        if($car->expire != CarModel::CAR_EXPIRE_NORMAL && $expire != CarModel::CAR_EXPIRE_NORMAL) {
            if(!$carModel->addExpireTime($car, $expire)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_DELETE_ERROR,
                    '[CarLogic] car exchange update car time error!',
                    (array)$car
                );
                return false;
            }
        }

        if($car->expire != CarModel::CAR_EXPIRE_NORMAL) {
            if(!$carModel->changeExpire($car, $expire)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_DELETE_ERROR,
                    '[CarLogic] car exchange expire error!',
                    (array)$car
                );
                return true;
            }
        }

        // 默认没有来源则不折算
        if($itemID == 0) {
            return true;
        }

        if(!$carModel->carExchange($itemID, $num)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_DELETE_ERROR,
                '[CarLogic] car exchange error!',
                (array)$car
            );
            return false;
        }
        return true;
    }

    private function initSkillData(int $carID, int $level):bool {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $carCfg = $this->getTitle(
                TemplateDefine::TYPE_CAR_AGGRANDIZEMENT,
                            $this->getCarAggrandizementID($carID, $level)
                        );
        $car = $carModel->searchCarByCarID($carID);
        if(is_null($car)) {
            return false;
        }
        return true;
    }

    /**
     * 获取强化表id
     * @param int $carID
     * @param int $level
     * @return int
     */
    private function getCarAggrandizementID(int $carID, int $level):int {
        return $carID * 100 + $level;
    }

    private function checkLevelIsMax(carData $car):bool {
        $beForeCarID = $car->carID;
        $newCar = $this->getTitle(
            TemplateDefine::TYPE_CAR_AGGRANDIZEMENT,
            $this->getCarAggrandizementID($car->carID,
                $car->level+1)
        );
        if(is_null($newCar)) {
            return false;
        }
        if($beForeCarID != $newCar[TemplateCarAggrandizement::CarId]) {
            return false;
        }
        return true;
    }

    private function checkNumCanEnough(array $consume, string $type):bool {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);

        if(empty($consume)) {
            return true;
        }

        foreach($consume as $id=>$num) {
            $haveNum = 0;
            switch($type) {
                case $carModel::ITEM:
                    $haveNum = $carModel->carGetItemNum($id);
                    break;
                case $carModel::MONEY:
                    $haveNum = $carModel->getMoney($id);
                    break;
            }
            if($haveNum < $num) {
                return false;
            }
        }
        return true;
    }

    private function upGradeConsume(array $consume, string $type):bool {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);

        if(empty($consume)) {
            return true;
        }
        foreach($consume as $id=>$num) {
            switch($type) {
                case $carModel::ITEM:
                    if(!$carModel->carSubItemByTID($id, $num)) {
                        LogMark::getInstance()->markError(
                            GameErrorCode::DATA_UPDATE_ERROR,
                            '[CarLogic] up grade consume item error!'
                        );
                        return false;
                    }
                    break;
                case $carModel::MONEY:
                    if(!$carModel->subMoney($id, $num)) {
                        LogMark::getInstance()->markError(
                            GameErrorCode::DATA_UPDATE_ERROR,
                            '[CarLogic] up grade consume money error!'
                        );
                        return false;
                    }
                    break;
            }
        }
        return true;
    }

    private function upGradeReward(array $reward): bool {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);

        if(empty($reward)) {
            return true;
        }
        $this->setLogAddItemSource(GameConstantDefine::ITEM_ADD_SOURCE_CAR_LV_UP_REWARD);
        foreach ($reward as $id=>$num) {
            if(!$carModel->carGainItem($id, $num)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_UPDATE_ERROR,
                    '[CarLogic] up grade get reward error!'
                );
                return false;
            }
        }
        return true;
    }

    // 查询赛车
    public function searchPlayerCar():array {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $carArr = $carModel->getPlayerCars();
        $data = array();
        foreach($carArr as $car) {
            $carDataSinger = new CarDataSingle();
            $carDataSinger->setUid((int)$car->uid);
            $carDataSinger->setCarID((int)$car->carID);
            $carDataSinger->setLevel((int)$car->level);
            $carDataSinger->setActiveSkill((int)$car->activeSkill);
            $carDataSinger->setPassiveSkill($car->passiveSkill);
            $carDataSinger->setProficiency((int)$car->proficiency);
            $carDataSinger->setExpire((int)$car->expire);
            $carDataSinger->setState((int)$car->state);
            $carDataSinger->setAttr($carModel->refitAttr($carModel->getCarRefitData($car->uid)));
            $carDataSinger->setProficiencyLv($car->proficiencyLv);
            $carDataSinger->setProficiencyReward(json_decode($car->proficiencyReward, true));
            $carDataSinger->setCreateTime($car->createTime);
            $data[] = $carDataSinger;
        }
        return $data;
    }

    // 通过carID 查询车信息
    public function searchCarDataByCarID(int $carID): ?carData {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $car = $carModel->searchCarByCarID($carID);
        if(is_null($car)) {
            LogMark::getInstance()->markDebug(
                '[CarLogic] searchCarDataByCarID car not found',
                array(
                    "carId" => $carID
                )
            );
        }
        return $car;
    }

    // 通过uid查询赛车
    public function getCarByCarUID(int $uid): ?carData {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $car = $carModel->searchCarByUid($uid);
        if(is_null($car)) {
            LogMark::getInstance()->markDebug(
                '[CarLogic] searchCarDataByCarID car not found',
                array(
                    "carUid" => $uid
                )
            );
            return null;
        }
        return $car;
    }

    // 更换赛车
    public function replacePlayerCar(int $uid, int &$code):bool
    {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $car = $carModel->searchCarByUid($uid);
        if(is_null($car)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_SEARCH_ERROR,
                '[CarLogic] replaceCar find car by uid error!'
            );
            $code = ClientErrorCode::ERROR_CAR_NOT_EXIST;
            return false;
        }
        //检查过期
        if ($car->expire != CarModel::CAR_EXPIRE_NORMAL && Utils::getServerTimestamp() >= $car->expire) {
            LogMark::getInstance()->markDebug(
                '[CarLogic] replaceCar time expire',
                array(
                    "carId" => $car->carID,
                    "expireTime" => $car->expire
                )
            );
            $code = ClientErrorCode::CAR_TIME_EXPIRE;
            return false;
        }

        if(!$carModel->carReplace([AccountData::DB_DEFAULT_CAR => $car->uid, AccountData::DB_DEFAULT_CAT_TPL => $car->carID])) {
            $code = ClientErrorCode::CAR_ERROR;
            return false;
        }
        return true;
    }

    //增加赛车熟练度
    public function addCarProficiency(int $carId, int $addNum, int $matchType = 0)
    {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $car = $carModel->searchCarByCarID($carId);
        if(is_null($car)) {
            LogMark::getInstance()->markDebug(
                '[CarLogic] addCarProficiency find car by id error!',
                array(
                    "carId" => $carId
                )
            );
            return;
        }
        //检查比赛模式是否加熟练度
        if ($matchType > 0) {
            $config = $this->getTitle(TemplateDefine::TYPE_COMPETITION_MODE, $matchType);
            if (is_null($config)) {
                return;
            }
            if ($config[TemplateCompetitionMode::WhetherPro] == 0) {
                return;
            }
        }
        //双倍熟练度收益,必须为比赛添加
        if ($matchType > 0 && $this->checkBuffActivate(AccountData::DB_BUFF_DOUBLE_PROFICIENCY)) {
            $addNum *= 2;
        }
        $carModel->changeProficiency($car, $addNum);
        $carModel->sendCarPacket();
    }

    //GM修改赛车熟练度
    public function gmAddCarProficiency(carData $car, int $lv,  int $exp)
    {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        if ($exp - $car->proficiency > 0) {
            $carModel->changeProficiency($car, $exp - $car->proficiency);
        }
        if ($lv > $car->proficiencyLv) {
            $addLv = $lv - $car->proficiencyLv;
            $car->proficiencyLv += $lv - $car->proficiencyLv;
            $car->saveDB();
            $carModel->addCarPacket($car);
            $this->addTotalProficiencyLv($addLv);
        }
        $carModel->sendCarPacket();
    }

    /**
     * 搜索改装数据
     * @param int $uid
     * @return array
     */
    public function searchRefitData(int $uid): array
    {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $carData = $carModel->getCarRefitData($uid);
        return array(
            "Attr" => $carModel->refitAttr($carData),
        );
    }

    /**
     * 赛车改装
     * @param int $uid
     * @param int $sys
     * @param $result
     * @return bool
     */
    public function makeRefit(int $uid, int $sys, &$result): bool
    {
        $this->setLogConsumeItemSource(GameConstantDefine::ITEM_CONSUME_SOURCE_CAR_REFIT);
        $result = [
            "Code" => ErrorDefine::SUCCESS,
            "Attr" => "",
        ];
        //连续负增长次数
        $ruleConn = $this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_Car_Refit_Random_Rule_Conn, "Const_num");
        //最大负增长条数
        $ruleMax = $this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_Car_Refit_Random_Rule_Max, "Const_num");

        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);
        $carRefitData = $carModel->getCarRefitData($uid);
        /**
         * @var carData $car
         */
        $car = $carModel->getCarData($uid);
        $carQuality = $this->getTitle(TemplateDefine::TYPE_CAR, $car->carID)[TemplateCar::Quality];
        if (is_null($car)){
            $result["Code"] = ClientErrorCode::ERROR_CAR_NOT_EXIST;
            return false;
        }
        //判断新旧的改装值是否相同,如果有变化则扣除道具,如果没有变化则不扣除
        $carRefitData["checkStatus"] = false;
        // 1 获取当前的解锁等级对应表
        // 2 获取车辆等级对应的最大上限值表
        $this->refitDataProcess($car->level, $sys, $carRefitData, $ruleMax, $ruleConn, (int)$carQuality);
        if ($carRefitData["checkStatus"]){
            //扣除道具
            if (!$this->consumeRefitItem($code, $carQuality)){
                $result["Code"] = $code;
                return false;
            }
            //更新数据
            if (!$carModel->updateRefit($uid, $carRefitData)){
                $result["Code"] =  ClientErrorCode::ERROR_CAT_REFIT_UPDATE_FAIL;
                return false;
            }
        }else{
            $result["Code"] = ClientErrorCode::ERROR_CAT_REFIT_FULL_LEVEL;
            return false;
        }
        $result["Attr"] = $carModel->refitAttr($carRefitData);
        // 触发任务
        $param = array(
            GameConstantDefine::EVENT_KEY_CAR_ID => $car->carID,
            GameConstantDefine::EVENT_KEY_NUM => 1,  //改造次数
            GameConstantDefine::EVENT_KEY_CAR_REFIT_SYS_ID => $sys, //系统id
        );
        $this->triggerEvent(EventTypeDefine::EVENT_TYPE_TASK_CAR_REFIT, $param);
        $this->addEventConditionValue(
            $this->getCarRefitKey($car->carID, $sys),
            1
        );
        return true;
    }
    //数据处理
    public function refitDataProcess($nowCarLevel, $sys, &$carData, $ruleMax, $ruleConn, $carQuality): ?bool
    {
        //当前车辆等级
        // 1 获取当前的解锁等级对应表
        // 2 获取车辆等级对应的最大上限值表
        $tplData = $this->getTitle(TemplateDefine::TYPE_DEEPMOD, $sys);
        if (is_null($tplData)) {
            $result["Code"] = ClientErrorCode::ERROR_CAT_SYS_NOT_EXIT;
            return false;
        }
        /**
         * @param array $unlock 每个解锁等级下对应的属性Id
         */
        $unlock = $tplData[1];
        /**
         * @param array $tpl_IncMax 每个属性类型中每个车辆等级对应的最大上限值
         */
        $tpl_IncMax = $tplData[2];
        /**
         * @param array $tpl_TypeId 每个属性类型中的所有属于当前属性的子属性Id对应的等级
         */
        $tpl_TypeId = $tplData[3];  //当前系统下的所有属性类型.包括未解锁的

        $showTypeAtt = [];
        foreach ($unlock as $level => $ids){
            if ($nowCarLevel < $level)
            {
                continue;
            }
            foreach ($ids as $id)
            {
                $showTypeAtt[$tplData[$id][TemplateCarDeepmod::TypeAtt]] = $tplData[$id][TemplateCarDeepmod::TypeAtt];
            }
        }
        // 当前等级下可以使用的属性数据表
        // 当前等级下每个属性类型Type_att的最大上限值
        // 数据表的字段对应当前等级最大上限值   BaseSpeed=>0.5
        $dbAttrLevelIncMax = [];
        foreach (CarDeepmodData::DB_TABLE_TYPE_MAP as $att => $typeAtt)
        {
            if (!isset($tpl_IncMax[$typeAtt][$nowCarLevel][$carQuality]))
            {
                continue;
            }
            if (!isset($showTypeAtt[$typeAtt]))
            {
                continue;
            }
            $dbAttrLevelIncMax[$typeAtt] = $tpl_IncMax[$typeAtt][$nowCarLevel][$carQuality];
        }

        //根据可以筛选的属性字段中查询具体的属性Id
        $dbAttrIds = [];
        foreach ($dbAttrLevelIncMax as $typeAtt=>$incMax)
        {
            if (!isset($tpl_TypeId[$typeAtt]))
            {
                continue;
            }
            foreach ($tpl_TypeId[$typeAtt] as $tplId => $tplCarLevel)
            {
                if ($nowCarLevel < $tplCarLevel)
                {
                    continue;
                }
                $dbAttrIds[$typeAtt][$tplId] = $tplData[$tplId];
            }
        }

        $this->makeRefitAttrRandom($dbAttrIds, $dbAttrLevelIncMax, $carData, $ruleMax, $ruleConn, $sys, $carQuality);
        return true;
    }
    /**
     * 随机改装属性
     * @param array $attr 模板
     * @param array $incMax 当前等级可以达到的最大的上限值
     * @param array $carData 当前服务器存储的改装值
     * @param int $ruleMax 规则1
     * @param int $ruleConn 规则2
     * @return array
     */
    public function makeRefitAttrRandom($attr, $incMax, &$carData, $ruleMax=2, $ruleConn=3, $sys = 1, $carQuality = 0):
    bool
    {
        $rule1 = json_decode($carData[CarDeepmodData::DB_RANDOM_ATTR], true);
        foreach ($attr as $typeAtt => $params)
        {
            $rule2 = [];
            foreach($params as $tplId => $param)
            {
                if($param[TemplateCarDeepmod::Quality] != $carQuality) {
                    continue;
                }
                $attrType = $param[TemplateCarDeepmod::TypeAtt];
                $Index = CarDeepmodData::DB_SYS_TYPE[$sys][$attrType];

                $attrVal = &$carData[CarDeepmodData::DB_KEY_MAP_TEMPLE[$Index]];
                if ($attrVal >= $param[TemplateCarDeepmod::IncMin] && $attrVal < $param[TemplateCarDeepmod::IncMax])
                {
                    $carData["checkStatus"] = true;
                    //开始随机执行
                    $random = random_int($param[TemplateCarDeepmod::SectionF], $param[TemplateCarDeepmod::SectionL]);
                    if ($random < 0) {
                        $rule2[] = $tplId;
                        if (count($rule2) > $ruleMax) {
                            $random = abs($random);
                        }
                        if (!empty($rule1[$tplId]) && $rule1[$tplId] >= $ruleConn) {
                            unset($rule1[$tplId]);
                            $random = $param[TemplateCarDeepmod::SectionL];
                        } elseif (empty($rule1[$tplId])) {
                            $rule1[$tplId] = 1;
                        } else {
                            $rule1[$tplId] += 1;
                        }
                    }else{
                        if (!empty($rule1[$tplId])) {
                            unset($rule1[$tplId]);
                        }
                    }
                    $attrVal += $random * $param[TemplateCarDeepmod::Ratio];
                    if ($attrVal <= 0) {
                        $attrVal = 0;
                    }
                    if ($attrVal > $incMax[$param[TemplateCarDeepmod::TypeAtt]]) {
                        $attrVal = $incMax[$param[TemplateCarDeepmod::TypeAtt]];
                    }
                }
            }
        }
        $carData[CarDeepmodData::DB_RANDOM_ATTR] = json_encode($rule1);
        return true;
    }

    //赛车改造扣除道具
    public function consumeRefitItem(&$code, $carQuality): bool
    {
        /**
         * @var CarModel $carModel
         */
        $carModel = ModelManager::getInstance()->getModel(ModelTypeDefine::CAR);

        //道具
        $item_type = $this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_Car_Refit_Consume_Item, "Const_num");
        switch ($carQuality) {
            case $carModel::CAR_QUALITY_A:
                $item_num = $this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_Car_Refit_Consume_Num_A, "Const_num");
                $money_num = $this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_Car_Refit_Money_Num_A, "Const_num");
                break;
            case $carModel::CAR_QUALITY_B:
                $item_num = $this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_Car_Refit_Consume_Num_B, "Const_num");
                $money_num = $this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_Car_Refit_Money_Num_B, "Const_num");
                break;
            case $carModel::CAR_QUALITY_S:
                $item_num = $this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_Car_Refit_Consume_Num_S, "Const_num");
                $money_num = $this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_Car_Refit_Money_Num_S, "Const_num");
                break;
                // TODO: 后续加 各种品质类型车辆
            default;
                $item_num = 0;
                $money_num = 0;
        }
        $item = [
            $item_type => $item_num
        ];
        // 检测道具是否充足
        if(!$this->checkNumCanEnough($item, $carModel::ITEM)) {
            $code = ClientErrorCode::ERROR_CAR_REFIT_PROP_NOT_ENOUGH;
            return false;
        }
        // 消耗道具
        if(!$this->upGradeConsume($item, $carModel::ITEM)) {
            $code =  ClientErrorCode::ERROR_CAR_REFIT_PROP_NOT_ENOUGH;
            return false;
        }

        //货币
        $money_type = $this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_Car_Refit_Money, "Const_num");

        $money = [
            $money_type => $money_num
        ];
        // 检测货币是否充足
        if(!$this->checkNumCanEnough($money, $carModel::MONEY)) {
            $code =  ClientErrorCode::ERROR_CAR_REFIT_MONEY_NOT_ENOUGH;
            return false;
        }
        // 消耗货币
        if(!$this->upGradeConsume($money, $carModel::MONEY)) {
            $code =  ClientErrorCode::ERROR_CAR_REFIT_MONEY_NOT_ENOUGH;
            return false;
        }
        return true;
    }

    //根据车类型 记录车使用次数
    public function recordCarUseNum(int $carId)
    {
        //查询车类型
        $carConfig = $this->getTitle(TemplateDefine::TYPE_CAR, $carId);
        if (is_null($carConfig)) {
            LogMark::getInstance()->markDebug(
                "[CarLogic] not fount car config",
                array(
                    "carId" => $carId
                )
            );
            return;
        }
        $key = null;
        switch ($carConfig[TemplateCar::Positioning])
        {
            case TemplateCar::Positioning_Race:
                $key = AccountData::DB_CAR_USE_NUM_RACE;
                break;
            case TemplateCar::Positioning_Jam:
                $key = AccountData::DB_CAR_USE_NUM_JAM;
                break;
            case TemplateCar::Positioning_Help:
                $key = AccountData::DB_CAR_USE_NUM_HELP;
                break;
        }
        if (is_null($key)) {
            LogMark::getInstance()->markDebug(
                "[CarLogic] car Positioning error",
                array(
                    "carId" => $carId,
                    "config" => json_encode($carConfig)
                )
            );
            return;
        }
        //增加车使用次数
        /**
         * @var AccountModel $accountModel
         */
        $accountModel = ModelManager::getInstance()->getModel(ModelTypeDefine::ACCOUNT);
        $accountModel->increaseAccountValue($key, 1);
    }

    //--------------新车通知消息--临时用-----------------------

    public function addNewCarNotice(int $carId, int $playerId)
    {
        $carNoticeData = new CarNoticeData($playerId);
        $newCarNotice = $carNoticeData->searchDB();
        if (!in_array($carId, $newCarNotice)) {
            $newCarNotice[] = $carId;
            $carNoticeData->updateDB($newCarNotice);
        }
    }

    public function sendNewCarNotice(int $playerId, bool $addPacket = false)
    {
        $carNoticeData = new CarNoticeData($playerId);
        $newCarNotice = $carNoticeData->searchDB();
        if (!empty($newCarNotice)) {
            $message = new GCNewCarNotice();
            $message->setNewCarId($newCarNotice);
            if ($addPacket) {
                $this->addPacket(PacketId::GC_NewCarNotice, $message);
            } else {
                SendMessage::getInstance()->sendClient(PacketId::GC_NewCarNotice, $message);
            }
        }
    }
}
