<?php
/**
 * CarModel.php
 * 赛车类
 */

namespace  Game\Model\Car;

use Framework\Define\ErrorDefine;
use Framework\Log\LogMark;
use Framework\Network\SendMessage;
use Framework\DB\Handler\PlayerDBHandler;
use Framework\Lib\Utils;
use Framework\Logic\TimerLogic;
use Game\Config\GameConfig;
use Game\Constant\ConstTemplate\TemplateCarAggrandizement;
use Game\Constant\ConstTemplate\TemplateProficiency;
use Game\Constant\DBTableDefine;
use Game\Constant\EventTypeDefine;
use Game\Constant\GameConstantDefine;
use Game\Constant\GameErrorCode;
use Game\Constant\ModelTypeDefine;
use Game\Constant\TemplateDefine;
use Game\Data\AccountData;
use Game\Data\Car\CarData;
use Game\Data\Car\CarExteriorData;
use Game\Data\Car\CarStatisticsData;
use Game\Data\Car\CarDeepmodData;
use Game\Logic\ItemLogic;
use Game\Logic\MoneyLogic;
use Game\Logic\ProficiencyLogic;
use Game\Logic\RankLogic;
use Game\Protobuf\CarDataSingle;
use Game\Protobuf\GCUpdateCarRecv;
use Game\Protobuf\PacketId;
use Framework\Logic\PacketCacheLogic;
use Game\Logic\AccountLogic;
Class CarModel {

    use PlayerDBHandler;
    use TimerLogic;
    use ItemLogic;
    use MoneyLogic;
    use PacketCacheLogic;
    use RankLogic;
    use ProficiencyLogic;
    use AccountLogic;

    public int $playerId;

    public const IS_OPEN = 1;       // 开启车辆

    public const STATE_NORMAL = 0;  // 车辆正常使用
    public const STATE_TIMEOUT = 1; // 时间失效车辆

    public const CAR_EXPIRE_NORMAL = 0; // 永久车辆

    public const ITEM = 'item';
    public const MONEY = 'money';

    public const CAR_QUALITY_C = 1;
    public const CAR_QUALITY_B = 2;
    public const CAR_QUALITY_A = 3;
    public const CAR_QUALITY_S = 4;
    public const CAR_QUALITY_SS = 5;

    public const ID = 'Id';
    public const CAR_ID = 'CarID';
    public const LEVEL = 'Level';
    public const ACTIVE_SKILL = 'ActiveSkill';
    public const PASSIVE_SKILL = 'PassiveSkill';
    public const EXPIRE = 'Expire';
    public const STATE = 'State';
    public const PROFICIENCY = 'Proficiency';
    public const ATTR = 'Attr';
    public const PERFORMANCE = 'Performance';

    private GCUpdateCarRecv $updateCar;
    private array          $sendCarList;

    public function __construct()
    {
        $this->sendCarList = array();
        $this->updateCar   = new GCUpdateCarRecv();
    }

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

    // 获取玩家赛车信息
    public function searchCarByCarID(int $carID): ?CarData {
        $arr = [];
        if(!$this->searchRank(DBTableDefine::TABLE_CAR, $this->playerId, $carID, $carID, $arr)) {
            return null;
        }
        if(empty($arr)) {
            return null;
        }
        foreach ($arr as $titleID=>$score) {
            $car = $this->getCarData($titleID);
            if(is_null($car)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_SEARCH_ERROR,
                    '[CarModel] searchCarByCarID error!',
                    array(
                        "carUid" => $titleID,
                        "carId" => $score
                    )
                );
                return null;
            }
            return $car;
        }
        return null;
    }

    // 获取玩家赛车信息
    public function searchCarByUid(int $uid): ?CarData {
        $car = $this->getCarData($uid);
        if(is_null($car)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_SEARCH_ERROR,
                '[CarModel] searchCarByUid error!',
                array(
                    "carUid" => $uid,
                )
            );
            return null;
        }
        return $car;
    }

    public function getCarData(int $uid, int $playerID = 0): ?CarData
    {
        if(empty($playerID)) {
            $playerID = $this->playerId;
        }
        $car = new CarData($playerID, $uid);
        if(!$car->searchCar()) {
            return null;
        }
        return $car;
    }

    public function getCarExterior(int $uid, int $playerID = 0): ?CarExteriorData
    {
        if(empty($playerID)) {
            $playerID = $this->playerId;
        }
        $carExterior = new CarExteriorData($playerID, $uid);
        if(!$carExterior->searchExterior()) {
            return null;
        }
        return $carExterior;
    }

    public function createCar(int $carID, int $level = 1, int $expire = 0): bool {
        $car = new CarData(
            $this->playerId,
            $this->makeCarId(),
            $carID,
            $level,
            $expire,
            self::STATE_NORMAL,
        );
        $performance = $this->getPerformance($carID, $level);
        $car->setPerformance($performance);
        //初始熟练度为1级
        $car->setProficiencyLv(1);
        $car->setProficiencyReward("[]");
        $car->setCreateTime(Utils::getServerTimestamp());
        if(!$car->createCar()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                '[CarModel] create car error!', (array)$car
            );
            return false;
        }
        //获得新车,总熟练度+1
        $this->addTotalProficiencyLv(1);
        //创建统计数据
        $carStatisticsData = new CarStatisticsData($this->playerId);
        $carStatisticsData->initData($car->uid);
        $this->addCarPacket($car);

        // 创建外观改装数据
        $carExterior = new CarExteriorData($this->playerId, $car->uid);
        if(!$carExterior->createDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                '[carModel] create car exterior error!', (array)$car
            );
            return false;
        }

        // 创建深度改装的数据
        $carDeep = new CarDeepmodData($this->playerId, $car->uid);
        if (!$carDeep->createDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                '[CarModel] create car deepmod error!', (array)$car
            );
            return false;
        }
        // 车辆榜数据更新

        return true;
    }

    // 获取基础性能分
    public function getPerformance(int $carID, int $level): int {
        $performance = 0;
        if($level == 1) {
            $performance = $this->getTitle(
                TemplateDefine::TYPE_CAR_AGGRANDIZEMENT,
                $this->getCarAggrandizementID($carID, $level))[TemplateCarAggrandizement::Performance];
        } else {
            for($i = 1; $i <= $level; $i++) {
                $performance += $this->getTitle(
                    TemplateDefine::TYPE_CAR_AGGRANDIZEMENT,
                    $this->getCarAggrandizementID($carID, $i))[TemplateCarAggrandizement::Performance];
            }
        }
        return $performance;
    }

    public function changeLevel(carData $car, int $level):bool {
        $car->setLevel($level);
        if(!$car->saveDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] change car level error!', (array)$car
            );
            return false;
        }
        $this->addCarPacket($car);
        return true;
    }

    public function changePerformance(carData $car, int $performance):bool {
        $car->setPerformance($car->performance + $performance);
        if(!$car->saveDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] change car performance error!', (array)$car
            );
            return false;
        }
        $this->addCarPacket($car);
        return true;
    }

    public function changeState(carData $car, int $state):bool {
        $car->setState($state);
        if(!$car->saveDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] change car time error!', (array)$car
            );
            return false;
        }
        $this->addCarPacket($car);
        return true;
    }

    //增加车熟练度
    public function changeProficiency(carData $car, int $addNum): bool
    {
        $car->proficiency += $addNum;
        $oldLv = $car->proficiencyLv;
        //检查是否超过上限
        $configData = $this->getTitle(TemplateDefine::TYPE_PROFICIENCY_CAR, $car->carID);
        if (is_null($configData)) {
            //没有配置的车,只加熟练度,不更新熟练度等级
            LogMark::getInstance()->markDebug(
                "[CarModel] not found car proficiency config",
                array(
                    "carId" => $car->carID
                )
            );
        } else {
            //永久车升级,限时车只增加经验
            if ($car->expire == self::CAR_EXPIRE_NORMAL) {
                //检查升级
                $maxLv = count($configData);
                while ($car->proficiency > 0) {
                    if ($car->proficiencyLv >= $maxLv) {
                        break;
                    }
                    $needExp = $this->getUpProficiencyExp($configData, $car->proficiencyLv);
                    if ($car->proficiency >= $needExp) {
                        $car->proficiencyLv++;
                        $car->proficiency -= $needExp;
                    } else {
                        break;
                    }
                }
            }
        }
        $car->setProficiency($car->proficiency);
        if(!$car->saveDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] change car proficiency error!', (array)$car
            );
            return false;
        }
        if ($car->proficiencyLv - $oldLv > 0) {
            //升级 更新总等级
            $this->addTotalProficiencyLv($car->proficiencyLv - $oldLv);
            //通知更新
            $this->sendProficiencyDataMessage($this->getTotalProficiencyData());
            //车熟练度
            $param = array(
                GameConstantDefine::EVENT_KEY_CAR_ID => $car->carID,
                GameConstantDefine::EVENT_KEY_NUM => $car->proficiencyLv - $oldLv,
            );
            $this->triggerEvent(EventTypeDefine::EVENT_TYPE_TASK_CAR_PROFICIENCY, $param);
        }
        $this->addCarPacket($car);
        return true;
    }

    //获取升级熟练度对应等级经验
    private function getUpProficiencyExp(array $configData, int $lv): int
    {
        return $configData[$lv][TemplateProficiency::Exp];
    }

    /**
     * 修改赛车到指定时间
     * @param CarData $car
     * @param int $expire // 0 车辆时间改为永久
     * @return bool
     */
    public function changeExpire(carData $car, int $expire):bool {

        if($expire == self::CAR_EXPIRE_NORMAL) {
            if(!$this->delTimer(ModelTypeDefine::CAR, $car->uid)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_UPDATE_ERROR,
                    '[CarModel] change expire del timer error!', (array)$car
                );
                return false;
            }
        } else {
            if(!$this->addTimer(ModelTypeDefine::CAR,$car->uid, $expire)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_UPDATE_ERROR,
                    '[CarModel] add car expire time error!', (array)$car
                );
                return false;
            }
        }
        $car->setExpire($expire);
        if(!$car->saveDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] change car time error!', (array)$car
            );
            return false;
        }
        $this->addCarPacket($car);
        return true;
    }

    /**
     * 限时赛车增加时间
     * @param CarData $car
     * @param int $time
     * @return bool
     */
    public function addExpireTime(carData $car, int $time): bool {
        $newTime = $car->expire + ($time - Utils::getServerTimestamp());
        if(!$this->addTimer(ModelTypeDefine::CAR, $car->uid, $newTime)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] add car expire time len error!', (array)$car
            );
            return false;
        }
        $car->setExpire($newTime);
        if(!$car->saveDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] change car time error!', (array)$car
            );
            return false;
        }
        $this->addCarPacket($car);
        return true;
    }

    public function carSaveData(carData $car): bool {
        if(!$car->saveDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] car data save error!', (array)$car
            );
            return false;
        }
        $this->addCarPacket($car);
        return true;
    }

    // 创建唯一id
    public function makeCarId(): int
    {
        $index = $this->getUidIndex();
        return Utils::makeObjectID(GameConfig::getInstance()->SERVER_ID(), DBTableDefine::TABLE_CAR, $index);
    }

    public function timerExpire(array $expireData) {
        if(empty($expireData)) {
            LogMark::getInstance()->markError(
                ErrorDefine::REQUEST_DATA_INVALID,
                '[CarModel] timerExpire array empty!'
            );
        }

        foreach($expireData as $uid => $exp) {
            $car = $this->getCarData($uid);
            if(is_null($car)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::CAR_DATA_GET_FAILED,
                    '[CarModel] timer search car by uid obj is null!', (array)$car
                );
                continue;
            }
            if(!$this->changeState($car, self::STATE_TIMEOUT)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_UPDATE_ERROR,
                    '[CarModel] timer change state is time_out error!', (array)$car
                );
                continue;
            }
            $this->sendCarPacket();
        }
    }

    // 获取玩家所有车辆对象数组
    public function getPlayerCars(): array {
        $carData = array();
        $arr = array();
        if(!$this->getTitleList(DBTableDefine::TABLE_CAR, $this->playerId, $arr)) {
            return [];
        }
        if(empty($arr)) {
            return [];
        }
        foreach ($arr as $uid=>$carID) {
            $car = $this->getCarData($uid);
            if(!is_null($car)) {
                array_push($carData, $car);
            }
        }
        return $carData;
    }

    public function getSignData(int $playerID = 0):array {
        if(empty($playerID)) {
            $playerID = $this->playerId;
        }
        $carData = array();
        $arr = array();
        if(!$this->getTitleList(DBTableDefine::TABLE_CAR, $playerID, $arr)) {
            return [];
        }
        if(empty($arr)) {
            return [];
        }
        foreach ($arr as $uid=>$carID) {
            $car = $this->getCarData($uid, $playerID);
            $carExterior = $this->getCarExterior($uid, $playerID);

            $passiveSkill = array();
            if (Utils::IsJson($car->passiveSkill)) {
                $passiveSkill = json_decode($car->passiveSkill, true);
            }

            $line = array();
            $line[self::ID]            = $car->uid;
            $line[self::CAR_ID]        = $car->carID;
            $line[self::LEVEL]         = $car->level;
            $line[self::ACTIVE_SKILL]  = $car->activeSkill;
            $line[self::PASSIVE_SKILL] = $passiveSkill;
            $line[self::EXPIRE]        = $car->expire;
            $line[self::STATE]         = $car->state;
            $line[self::PROFICIENCY]   = $car->proficiency;
            $line[self::PERFORMANCE]   = $car->performance ?? 0;
            $line[self::ATTR]          = $this->refitAttr($this->getCarRefitData($uid));   //车辆改装数据
            $line[CarData::PROFICIENCY_LV] = $car->proficiencyLv;
            $line[CarData::PROFICIENCY_REWARD] = json_decode($car->proficiencyReward);
            $line[CarData::CREATE_TIME] = $car->createTime;

            if(isset($carExterior->skin)) {
                $line[CarExteriorData::DB_SKIN]          = $carExterior->skin;
                $line[CarExteriorData::DB_PAINT]         = $carExterior->paint;
                $line[CarExteriorData::DB_TAIL]          = $carExterior->tail;
                $line[CarExteriorData::DB_HOOD]          = $carExterior->hood;
                $line[CarExteriorData::DB_STICKER]       = $carExterior->sticker;
                $line[CarExteriorData::DB_LIGHT_STRIP]   = $carExterior->lightStrip;
                $line[CarExteriorData::DB_ORNAMENTS]     = $carExterior->ornaments;
                $line[CarExteriorData::DB_TIRE]          = $carExterior->tire;
                $line[CarExteriorData::DB_NITROGEN]      = $carExterior->nitrogen;
                $line[CarExteriorData::DB_HUB]           = $carExterior->hub;
                $line[CarExteriorData::DB_LICENSE_IMAGE] = $carExterior->licenseImage;
                $line[CarExteriorData::DB_LICENCE]       = $carExterior->licence;
            }

            if(!is_null($car)) {
                $carData[] = $line;
            }
        }
        return $carData;
    }

    // 更换车
    public function carReplace(array $arr): bool {
        if(!$this->saveAccountData($arr)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] model car replace error!',
                $arr
            );
            return false;
        }
        return true;
    }

    // 车折算
    public function carExchange(int $itemID, int $num): bool {
        if(!$this->Exchange($itemID, $num)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] car exchange error!',
                ['itemID' => $itemID, 'num' => $num]
            );
            return false;
        }
        return true;
    }

    // 道具总量获取
    public function carGetItemNum(int $itemID): int {
        $num = $this->getItemNumByTplID($itemID);
        if($num == 0) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] car get tplID ItemSum error!',
                ['itemID' => $itemID]
            );
        }
        return $num;
    }

    // 金币数量获取
    public function carGetMoneyNum(int $itemID, int $num): bool {
        if(!$this->Exchange($itemID, $num)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] car get money num error!',
                ['itemID' => $itemID, 'num' => $num]
            );
            return false;
        }
        return true;
    }

    // subItemByTid
    public function carSubItemByTID(int $tplID, int $num): bool {
        if($num === 0) {
            return true;
        }
        if(!$this->subItemByTID($tplID, $num)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] car sub item by tid error!',
                ['tplID' => $tplID, 'num' => $num]
            );
            return false;
        }
        return true;
    }

    // subMoney
    public function carSubMoney(int $type, int $value): bool {
        if(!$this->subMoney($type, $value)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] car sub money error!',
                ['type' => $type, 'value' => $value]
            );
            return false;
        }
        return true;
    }

    // gainItem
    public function carGainItem(int $tplID, int $itemNum): bool {
        if(!$this->gainItem($tplID, $itemNum)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] car gain item error!',
                ['tplID' => $tplID, 'num' => $itemNum]
            );
            return false;
        }
        return true;
    }

    public function addCarPacket(CarData $car) {
        $carMsg = new CarDataSingle();
        $carMsg->setUid($car->uid);
        $carMsg->setCarID($car->carID);
        $carMsg->setLevel($car->level);
        $carMsg->setActiveSkill($car->activeSkill);
        $carMsg->setPassiveSkill($car->passiveSkill);
        $carMsg->setExpire($car->expire);
        $carMsg->setState($car->state);
        $carMsg->setAttr($this->refitAttr($this->getCarRefitData($car->uid)));
        $carMsg->setPerformance($car->performance);
        $carMsg->setProficiencyLv($car->proficiencyLv);
        $carMsg->setProficiency($car->proficiency);
        $carMsg->setProficiencyReward(json_decode($car->proficiencyReward, true));
        $carMsg->setCreateTime($car->createTime);
        $this->sendCarList[] = $carMsg;
    }

    public function sendCarPacket()
    {
        if (!empty($this->sendCarList)) {
            $this->updateCar->setCar($this->sendCarList);
            SendMessage::getInstance()->sendClient(PacketId::GC_Car_Update_Recv, $this->updateCar);
            $this->clearSendMsg();
        }
    }

    public function addCarExec()
    {
        if (!empty($this->sendCarList)) {
            $this->updateCar->setCar($this->sendCarList);
            $this->addPacket(PacketId::GC_Car_Update_Recv, $this->updateCar);
            $this->clearSendMsg();
        }
    }

    private function clearSendMsg() {
        unset($this->sendCarList);
        $this->sendCarList = array();
    }

    //查询车辆改装数据
    public function getCarRefitData($uid)
    {
        return (new CarDeepmodData($this->playerId, $uid))->searchRefit();
    }
    // 生成数据
    public function refitAttr($carData): string
    {
        $res = [];
        foreach (CarDeepmodData::DB_KEY_MAP_TEMPLE as $key => $value) {
            $res[] = [
                'sysID' => CarDeepmodData::DB_TABLE_MAP[$key],
                'type' => CarDeepmodData::DB_TABLE_TYPE_MAP[$key],
                'val' => (float)$carData[$value],
            ];
        }
        return json_encode($res);
    }
    //更新车辆改装数据
    public function updateRefit($uid, $carData): bool
    {
        $carRefit = new CarDeepmodData($this->playerId, $uid);
        $carRefit->setBaseSpeed1($carData[CarDeepmodData::DB_BASE_SPEED1]);
        $carRefit->setBaseSpeed2($carData[CarDeepmodData::DB_BASE_SPEED2]);
        $carRefit->setBaseSpeed3($carData[CarDeepmodData::DB_BASE_SPEED3]);

        $carRefit->setNitrogenSpeed1($carData[CarDeepmodData::DB_NITROGEN_SPEED1]);
        $carRefit->setNitrogenSpeed2($carData[CarDeepmodData::DB_NITROGEN_SPEED2]);
        $carRefit->setNitrogenSpeed3($carData[CarDeepmodData::DB_NITROGEN_SPEED3]);

        $carRefit->setJetSpeed1($carData[CarDeepmodData::DB_JET_SPEED1]);
        $carRefit->setJetSpeed2($carData[CarDeepmodData::DB_JET_SPEED2]);
        $carRefit->setJetSpeed3($carData[CarDeepmodData::DB_JET_SPEED3]);

        $carRefit->setBaseAccelerate1($carData[CarDeepmodData::DB_BASE_ACCELERATE1]);
        $carRefit->setBaseAccelerate2($carData[CarDeepmodData::DB_BASE_ACCELERATE2]);
        $carRefit->setBaseAccelerate3($carData[CarDeepmodData::DB_BASE_ACCELERATE3]);

        $carRefit->setNitrogenAccelerate1($carData[CarDeepmodData::DB_NITROGEN_ACCELERATE1]);
        $carRefit->setNitrogenAccelerate2($carData[CarDeepmodData::DB_NITROGEN_ACCELERATE2]);
        $carRefit->setNitrogenAccelerate3($carData[CarDeepmodData::DB_NITROGEN_ACCELERATE3]);

        $carRefit->setJetAccelerate1($carData[CarDeepmodData::DB_JET_ACCELERATE1]);
        $carRefit->setJetAccelerate2($carData[CarDeepmodData::DB_JET_ACCELERATE2]);
        $carRefit->setJetAccelerate3($carData[CarDeepmodData::DB_JET_ACCELERATE3]);

        $carRefit->setNitrogenTime1($carData[CarDeepmodData::DB_NITROGEN_TIME1]);
        $carRefit->setNitrogenTime2($carData[CarDeepmodData::DB_NITROGEN_TIME2]);
        $carRefit->setNitrogenTime3($carData[CarDeepmodData::DB_NITROGEN_TIME3]);

        $carRefit->setJetTime1($carData[CarDeepmodData::DB_JET_TIME1]);
        $carRefit->setJetTime2($carData[CarDeepmodData::DB_JET_TIME2]);
        $carRefit->setJetTime3($carData[CarDeepmodData::DB_JET_TIME3]);

        $carRefit->setNitrogenAccumulation1($carData[CarDeepmodData::DB_NITROGEN_ACCUMULATION1]);
        $carRefit->setNitrogenAccumulation2($carData[CarDeepmodData::DB_NITROGEN_ACCUMULATION2]);
        $carRefit->setNitrogenAccumulation3($carData[CarDeepmodData::DB_NITROGEN_ACCUMULATION3]);

        $carRefit->setRandomAttr($carData[CarDeepmodData::DB_RANDOM_ATTR]);
        if (!$carRefit->updateDB()){
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarModel] car deepmod update  error!',
                ['carId' => $uid]
            );
            return false;
        }
        return true;
    }

    // 查找赛车外观改装数据
    public function getCarExteriorRefitData(int $uid):array {
        $exteriorRefit = new CarExteriorData($this->playerId, $uid);
        $data = $exteriorRefit->searchExteriorArr();
        if(!$data) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_SEARCH_ERROR,
                '[car model] get car exterior refit by car uid error!'
            );
            return [];
        }
        return $data;
    }

    //登录检查
    public function onLoginExec()
    {
        //检查当驾驶前车是否过期
        $drivingCarUid = $this->getAccountAttribute(AccountData::DB_DEFAULT_CAR);
        $car = $this->searchCarByUid($drivingCarUid);
        if (is_null($car)) {
            LogMark::getInstance()->markDebug(
                "[CarModel] onLoginExec not found driving car",
                array(
                    "carUid" => $drivingCarUid
                )
            );
            //当前驾驶车辆不存在
            $this->replaceToMaxPerformanceCar();
            return;
        }
        if ($car->expire != self::CAR_EXPIRE_NORMAL && Utils::getServerTimestamp() >= $car->expire) {
            //当前驾驶车辆过期
            $this->replaceToMaxPerformanceCar();
        }
    }

    //替换当前车为最高性能分最高的车
    private function replaceToMaxPerformanceCar()
    {
        $carArr = $this->getPlayerCars();
        $tmpPerformance = 0;
        $tmpCar = null;
        $now = Utils::getServerTimestamp();
        foreach ($carArr as $car) {
            /**
             * @var CarData $car
             */
            //非过期的车
            if ($car->expire == self::CAR_EXPIRE_NORMAL || $car->expire > $now) {
                if ($car->performance >= $tmpPerformance) {
                    $tmpPerformance = $car->performance;
                    $tmpCar = $car;
                }
            }
        }
        if (!is_null($tmpCar)) {
            $data = [
                AccountData::DB_DEFAULT_CAR => $tmpCar->uid,
                AccountData::DB_DEFAULT_CAT_TPL => $tmpCar->carID
            ];
            $this->saveAccountData($data);
        }
    }

    //查询赛车状态的改装件ItemId,日志用
    public function getCarExteriorItemIds(int $carUid): array
    {
        return (new CarExteriorData($this->playerId, $carUid))->getCarExteriorItemIdArr();
    }

    //检查改装件是否存在--抽奖用
    public function checkHasRefitId(int $refitId): bool
    {
        return (new CarExteriorData($this->playerId, 0))->checkHasRefitId($refitId);
    }
}
