<?php
/**
 * CarExteriorRefitModel.php
 * 赛车外观改装类
 */

namespace  Game\Model\Car;

use Framework\Log\LogMark;
use Framework\Network\SendMessage;
use Framework\DB\Handler\PlayerDBHandler;
use Framework\Lib\Utils;
use Framework\Logic\TemplateHelp;
use Game\Config\GameConfig;
use Game\Constant\CarExteriorRefitDefine;
use Game\Constant\ClientErrorCode;
use Game\Constant\ConstTemplate\TemplateAppearance;
use Game\Constant\ConstTemplate\TemplateCarAggrandizement;
use Game\Constant\ConstTemplate\TemplateConst;
use Game\Constant\ConstTemplate\TemplateItem;
use Game\Constant\DBTableDefine;
use Game\Constant\GameErrorCode;
use Game\Constant\TemplateDefine;
use Game\Data\Car\CarExteriorData;
use Game\Data\CarExteriorRefitData;
use Game\Logic\CarExteriorRefitLogic;
use Game\Protobuf\GCAddCarExteriorRefit;
use Game\Protobuf\GCSyncBindCarExteriorRefit;
use Game\Protobuf\GCSyncExteriorRefit;
use Game\Protobuf\PacketId;


Class CarExteriorRefitModel {

    use PlayerDBHandler;
    use TemplateHelp;
    use CarExteriorRefitLogic;

    public int $playerId;

    const IS_OPEN = 1;         // 开启此改装
    const LICENCE_NUM = 6;     // 六位字符串号牌
    const LICENCE_COUNT = 8;   // 六位字符串号牌
    const RAND_NUM = 100;      // 六位字符串号牌
    const NUMBER_INDEX = 100; // 筛选最大索引
    const NUMBER_SHIELD_INDEX = 100; // 屏蔽字最大索引

    const RAND_LICENCE = [
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
        'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    ];

    private GCSyncExteriorRefit $exteriorRefit;
    private GCAddCarExteriorRefit $addExteriorRefit;
    private GCSyncBindCarExteriorRefit $bindCarSync;

    public function __construct()
    {
        $this->exteriorRefit = new GCSyncExteriorRefit();
        $this->addExteriorRefit = new GCAddCarExteriorRefit();
        $this->bindCarSync = new GCSyncBindCarExteriorRefit();
    }

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

    // TODO:外观数据逻辑 ↓

    // 通过uid获取玩家外观改装信息
    public function searchExteriorRefitByUid(int $uid): ?CarExteriorRefitData {
        $refit = $this->getExteriorRefitData($uid);
        if(is_null($refit)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_SEARCH_ERROR,
                '[exteriorRefitModel] search car exterior refit by uid error!'
            );
            return null;
        }
        return $refit;
    }

    public function getExteriorRefitData(int $uid, int $playerID = 0): ?CarExteriorRefitData
    {
        if(empty($playerID)) {
            $playerID = $this->playerId;
        }
        $refit = new CarExteriorRefitData($playerID, $uid);
        if(!$refit->searchExteriorRefit()) {
            return null;
        }
        return $refit;
    }

    public function getERDataByRefitID($refitID, int $playerID = 0): array {
        if(empty($playerID)) {
            $playerID = $this->playerId;
        }
        $refit = new CarExteriorRefitData($playerID);
        $refit->playerID = $playerID;
        return $refit->getERDataByRefitID($refitID);
    }

    public function createExteriorRefit(int $carTplID, int $refitID, string $params = ""): ?CarExteriorRefitData {
        $getTime = Utils::getServerTimestamp();
        $refit = new CarExteriorRefitData(
            $this->playerId,
            $this->makeExteriorRefitId(),
            $refitID,
            $carTplID,
            $getTime,
            $params
        );
        if(!$refit->createCarExteriorRefit()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                '[exteriorRefitModel] create car exterior refit error!', (array)$refit
            );
            return null;
        }

        // 通过tplID（appearance）获取对应道具id
        $itemID = $this->getERItemIDByTplID($refitID);

        // 增加车辆改装分
        $this->addCarRefitRank(0, $itemID, TemplateItem::TYPE_CAR_REFIT);

        $this->initExteriorRefitPacket($refit);
        return $refit;
    }


    public function carExteriorRefitSaveData(CarExteriorRefitData $refit): bool {
        if(!$refit->saveDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[exteriorRefitModel] car exterior refit data save error!', (array)$refit
            );
            return false;
        }
        return true;
    }

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

    // 获取玩家所有车辆外观改装对象数组
    public function getPlayerExteriorRefits(): array {
        $refits = array();
        $arr = array();
        if(!$this->getTitleList(DBTableDefine::TABLE_EXTERIOR_REFIT, $this->playerId, $arr)) {
            return [];
        }
        if(empty($arr)) {
            return [];
        }
        foreach ($arr as $uid=>$carID) {
            $refit = $this->getExteriorRefitData($uid);
            if(!is_null($refit)) {
                $refits[] = $refit;
            }
        }
        return $refits;
    }

    public function getSignData(int $playerID = 0):array {
        if(empty($playerID)) {
            $playerID = $this->playerId;
        }
        $refitData = array();
        $arr = array();
        if(!$this->getTitleList(DBTableDefine::TABLE_EXTERIOR_REFIT, $playerID, $arr)) {
            return [];
        }
        if(empty($arr)) {
            return [];
        }

        foreach ($arr as $uid=>$carID) {
            $refit = $this->getExteriorRefitData($uid, $playerID);
            if(is_null($refitData)) {
                continue;
            }
            $line = array();
            $line[CarExteriorRefitData::UID]       = $refit->uid;
            $line[CarExteriorRefitData::TPL_ID]    = $refit->tplID;
            $line[CarExteriorRefitData::GET_TIME]  = $refit->getTime;
            $line[CarExteriorRefitData::PARAMS]  = $refit->params;
            $line[CarExteriorRefitData::CAR_ID]  = $refit->carID;
            if(!is_null($refit)) {
                $refitData[] = $line;
            }
        }
        return $refitData;
    }

    // TODO:车辆外观数据逻辑 ↓

    // 修改绑定car外观数据
    public function changeBindCarExteriorData(int $carUID, int $type, int $refitID):bool {
        $exteriorData = new CarExteriorData($this->playerId, $carUID);
        $field = CarExteriorRefitDefine::DB_REFIT_MAP[$type];
        $arr = json_decode($exteriorData->searchExteriorArr()[$field], true);
        if(!empty($arr)) {
            $newItem = [];
            foreach ($arr as $item) {
                if($item[CarExteriorData::DB_IS_USE] == CarExteriorData::DB_EXTERIOR_TRUE) {
                    $item[CarExteriorData::DB_IS_USE] = CarExteriorData::DB_EXTERIOR_NOT;
                }
                if($item[CarExteriorData::DB_UID] == $refitID) {
                    $item[CarExteriorData::DB_IS_USE] = CarExteriorData::DB_EXTERIOR_TRUE;
                }
                $newItem[] = $item;
            }
            $data = [$field => json_encode($newItem)];
        } else {
            $data = [$field => json_encode([
                CarExteriorData::DB_UID => $refitID,
                CarExteriorData::DB_GET_TIME => time(),
                CarExteriorData::DB_IS_USE => CarExteriorData::DB_EXTERIOR_TRUE,
            ])];
        }
        if(!$exteriorData->saveDB($data)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[exteriorRefitModel] update bind car exterior refit error!', (array)$exteriorData
            );
            return false;
        }

        // 重新计算性能分
        $this->computePerformanceScore($carUID);
        return true;
    }

    // 修改car外观数据id
    public function changeCarExteriorData(int $carUID, int $type, int $refitID):bool {
        $exteriorData = new CarExteriorData($this->playerId, $carUID);
        $field = CarExteriorRefitDefine::DB_REFIT_MAP[$type];
        if(!$exteriorData->saveDB([$field => $refitID])) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[exteriorRefitModel] update normal car exterior refit error!', (array)$exteriorData
            );
            return false;
        }
        // 重新计算性能分
        $this->computePerformanceScore($carUID);
        return true;
    }

    // 修改car外观数据 挂饰
    public function changeCarExteriorOrnaments(int $carUID, int $type, int $refitID, string $params):bool {
        $exteriorData = new CarExteriorData($this->playerId, $carUID);
        $data = json_encode([
            CarExteriorData::DB_UID => $refitID,
            CarExteriorData::DB_POSITION => $params,
        ]);
        $field = CarExteriorRefitDefine::DB_REFIT_MAP[$type];
        if(!$exteriorData->saveDB([$field => $data])) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[exteriorRefitModel] update normal car exterior refit error!', (array)$exteriorData
            );
            return false;
        }

        $refitData = new CarExteriorRefitData($this->playerId, $refitID);
        if($refitData->searchExteriorRefit()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_SEARCH_ERROR,
                '[exteriorRefitModel] search exterior refit error!', (array)$exteriorData
            );
            return false;
        }
        $refitData->setParams($params);
        if(!$refitData->saveDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[exteriorRefitModel] update normal car exterior refit error!', (array)$exteriorData
            );
            return false;
        }
        // 重新计算性能分
        $this->computePerformanceScore($carUID);
        return true;
    }

    // 增加car外观数据 (针对多数组数据) 获取车的相应绑定数据使用
    public function addCarExteriorData(int $carUID, int $type, int $refitID, string $params): bool {
        $exteriorData = new CarExteriorData($this->playerId, $carUID);
        $erData = $exteriorData->searchExteriorArr();
        $field = CarExteriorRefitDefine::DB_REFIT_MAP[$type];
        $getTime = Utils::getServerTimestamp();
        if(empty($erData[$field])) {
            $data = json_encode([
                [
                    CarExteriorData::DB_UID => $refitID,
                    CarExteriorData::DB_GET_TIME => $getTime,
                    CarExteriorData::DB_IS_USE => CarExteriorData::DB_EXTERIOR_NOT,
                ]
            ]);
        } else {
            $arr = json_decode($erData[$field], true);
            $arr[] = [
                CarExteriorData::DB_UID => $refitID,
                CarExteriorData::DB_GET_TIME => $getTime,
                CarExteriorData::DB_IS_USE => CarExteriorData::DB_EXTERIOR_NOT,
            ];
            $data = json_encode($arr);
        }
        if(!$exteriorData->saveDB([$field => $data])) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[exteriorRefitModel] update add car exterior refit error!', (array)$data
            );
            return false;
        }
        // 同步car外观改装信息
        $exteriorData->searchExterior();
        $this->sendBindCarSyncPacket($exteriorData);
        // 重新计算性能分
        $this->computePerformanceScore($carUID);
        return true;
    }

    // 增加车贴到车数据上
    public function addExteriorRefitModel(int $carUID, int $type, int $refitID, string $params, int $num): bool {
        $exteriorData = new CarExteriorData($this->playerId, $carUID);
        $erData = $exteriorData->searchExteriorArr();
        if(!$exteriorData->searchExterior()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_SEARCH_ERROR,
                '[exteriorRefitModel] add car exterior refit but search error!', (array)$exteriorData
            );
            return false;
        }
        $field = CarExteriorRefitDefine::DB_REFIT_MAP[$type];
        if(empty($erData[$field])) {
            $data = json_encode([
                [
                    CarExteriorData::DB_UID => $refitID,
                    CarExteriorData::DB_SORT => $num,
                    CarExteriorData::DB_POSITION => $params,
                ]
            ], JSON_THROW_ON_ERROR);
        } else {
            $arr = json_decode($erData[$field], true);
            $numMax = $this->getTerm(TemplateDefine::TYPE_CONST, TemplateConst::Const_Exterior_Refit_Sticker_Max, "Const_num");

            if(count($arr) >= $numMax) {
                $this->appendAddExteriorRefitPacket(ClientErrorCode::EXTERIOR_REFIT_STICKER_IS_MAX);
                return false;
            }
            $arr[] = [
                CarExteriorData::DB_UID => $refitID,
                CarExteriorData::DB_SORT => $num,
                CarExteriorData::DB_POSITION => $params];
            $data = json_encode($arr);
        }

        if(!$exteriorData->saveDB([$field => $data])) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[exteriorRefitModel] update add car exterior refit error!', (array)$data
            );
            return false;
        }
        // 重新计算性能分
        $this->computePerformanceScore($carUID);
        return true;
    }

    // 删除绑定外观改装
    public function delBindCarExteriorRefit(int $carUID, int $type, int $refitID): bool {
        // erID*getTime*1|erID*getTime
        $exteriorData = new CarExteriorData($this->playerId, $carUID);
        $field = CarExteriorRefitDefine::DB_REFIT_MAP[$type];
        $strArr = json_decode($exteriorData->searchExteriorArr()[$field], true);
        $newItem = [];
        foreach ($strArr as $item) {
            if($item[CarExteriorData::DB_UID] === $refitID && $item[CarExteriorData::DB_IS_USE] ===
                CarExteriorData::DB_EXTERIOR_TRUE) {
                $item[CarExteriorData::DB_IS_USE] = CarExteriorData::DB_EXTERIOR_NOT;
            }
            $newItem[] = $item;
        }
        $data = [$field => json_encode($newItem)];

        if(!$exteriorData->saveDB($data)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarExteriorRefitModel] del exterior refit of bind car error!', (array)$exteriorData
            );
        }
        // 重新计算性能分
        $this->computePerformanceScore($carUID);
        return true;
    }

    // 删除正常外观改装
    public function delNormalExteriorRefit(int $carUID, int $type): bool {
        $exteriorData = new CarExteriorData($this->playerId, $carUID);
        $field = CarExteriorRefitDefine::DB_REFIT_MAP[$type];
        $data = [$field => ''];

        if(!$exteriorData->saveDB($data)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[CarExteriorRefitModel] del exterior refit of normal error!', (array)$exteriorData
            );
        }
        // 重新计算性能分
        $this->computePerformanceScore($carUID);
        return true;
    }

    // 删除贴纸和挂饰
    public function deleteCarExteriorData(int $carUID, int $type, int $refitID, int $num): bool {
        $exteriorData = new CarExteriorData($this->playerId, $carUID);
        $field = CarExteriorRefitDefine::DB_REFIT_MAP[$type];
        if($field == CarExteriorRefitDefine::DB_ORNAMENTS) {
            $this->delNormalExteriorRefit($carUID, $type);
        } else {
            $strArr = json_decode($exteriorData->searchExteriorArr()[$field], true);
            $newItem = [];
            foreach ($strArr as $item) {
                if($item[CarExteriorData::DB_UID] === $refitID && $item[CarExteriorData::DB_SORT] === $num) {
                    continue;
                }
                $newItem[] = $item;
            }
            if(empty($newItem)) {
                $data = [$field => ''];
            } else {
                $data = [$field => json_encode($newItem)];
            }

            if(!$exteriorData->saveDB($data)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_UPDATE_ERROR,
                    '[exteriorRefitModel] del car exterior refit of multi error!', (array)$exteriorData
                );
            }
        }
        // 重新计算性能分
        $this->computePerformanceScore($carUID);
        return true;
    }

    // 修改贴纸
    public function updateCarExteriorData(int $carUID, int $type, int $refitID, string $params, int $num): bool {
        // erID*num*param|erID*num*param
        $exteriorData = new CarExteriorData($this->playerId, $carUID);
        $field = CarExteriorRefitDefine::DB_REFIT_MAP[$type];

        $strArr = json_decode($exteriorData->searchExteriorArr()[$field], true);
        $newItem = [];
        foreach ($strArr as $item) {
            if($item[CarExteriorData::DB_UID] == $refitID && $item[CarExteriorData::DB_SORT] == $num) {
                $item[CarExteriorData::DB_POSITION] = $params;
            }
            $newItem[] = $item;
        }
        $data = [$field => json_encode($newItem)];
        if(!$exteriorData->saveDB($data)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[exteriorRefitModel] del bind car exterior refit error!', (array)$exteriorData
            );
            return false;
        }
        // 重新计算性能分
        $this->computePerformanceScore($carUID);
        return true;
    }

    public function getCarExteriorInfo(int $uid, &$exteriorRefits):bool {
        $exteriorData = new CarExteriorData($this->playerId, $uid);
        $exterior = $exteriorData->searchExteriorArr();
        foreach ($exterior as $key => $val) {
            if(empty($val)) {
                continue;
            }
            switch($key) {
                case CarExteriorData::DB_STICKER:
                    $arr = $this->execStickerData($val);
                    break;
                case CarExteriorData::DB_ORNAMENTS:
                    $arr = $this->execOrnamentsData($val);
                    break;
                case CarExteriorData::DB_LICENCE:
                    $arr = $this->execLicenceData($val);
                    break;
                case CarExteriorData::DB_SKIN:
                case CarExteriorData::DB_PAINT:
                case CarExteriorData::DB_LIGHT_STRIP:
                    $arr = $this->execBindCarData($val);
                    break;
                default:
                    $arr = $this->execNormalData($val);
                    break;
            }
            $exteriorRefits[$key] = $arr;
        }
        return true;
    }

    public function execStickerData(string $refit):array {
        $arrRefit = json_decode($refit, true);
        $resArr = [];
        foreach($arrRefit as $item) {
            $exteriorRefit = $this->getExteriorRefitData($item[CarExteriorData::DB_UID]);
            if(!is_null($exteriorRefit)) {
                $resArr[] = [
                    CarExteriorRefitData::TPL_ID => $exteriorRefit->tplID,
                    CarExteriorRefitData::PARAMS => $item[CarExteriorData::DB_POSITION],
                ];
            }
        }
        return $resArr;
    }
    public function execLicenceData(string $refit):array {
        $res = [];
        $exteriorRefit = $this->getExteriorRefitData($refit);
        if(!is_null($exteriorRefit)) {
            $res = [
                CarExteriorRefitData::TPL_ID => $exteriorRefit->tplID,
                CarExteriorRefitData::PARAMS => $exteriorRefit->params,
            ];
        }
        return $res;
    }

    public function execOrnamentsData(string $refit):array {
        $resArr = [];
        $arr = json_decode($refit, true);
        $exteriorRefit = $this->getExteriorRefitData($arr[CarExteriorData::DB_UID]);
        if(!is_null($exteriorRefit)) {
            $resArr = [
                CarExteriorRefitData::TPL_ID => $exteriorRefit->tplID,
                CarExteriorRefitData::PARAMS => $arr[CarExteriorData::DB_POSITION],
            ];
        }
        return $resArr;
    }

    public function execBindCarData(string $refit):int {
        $res = 0;
        $arrRefit = json_decode($refit, true);
        foreach($arrRefit as $item) {
            if($item[CarExteriorData::DB_IS_USE] == CarExteriorData::DB_EXTERIOR_TRUE) {
                $exteriorRefit = $this->getExteriorRefitData($item[CarExteriorData::DB_UID]);
                if(!is_null($exteriorRefit)) {
                    $res = $exteriorRefit->tplID;
                }
            }
        }
        return $res;
    }

    // 重新计算性能分 车基础分+改装分
    public function computePerformanceScore(int $uid): bool {
        $skin = $paint = $tail = $hood = $sticker = $lightStrip = $ornaments
            = $tire = $nitrogen = $hub = $licenseImage = $licence = 0;
        // 查询车辆改装信息 获取基础改装分
        $exteriorObj = new CarExteriorData($this->playerId, $uid);
        $exteriorData = $exteriorObj->searchExteriorArr();
        foreach($exteriorData as $field => $item) {
            // 特殊
            switch($field) {
                case CarExteriorRefitDefine::DB_SKIN:
                    $skin = $this->getBindCarScore($item);
                    break;
                case CarExteriorRefitDefine::DB_PAINT:
                    $paint = $this->getBindCarScore($item);
                    break;
                case CarExteriorRefitDefine::DB_TAIL:
                    $tail = $this->getNormalScore($item);
                    break;
                case CarExteriorRefitDefine::DB_HOOD:
                    $hood = $this->getNormalScore($item);
                    break;
                case CarExteriorRefitDefine::DB_STICKER:
                    $skin = $this->getStickerScore($item);
                    break;
                case CarExteriorRefitDefine::DB_LIGHT_STRIP:
                    $sticker = $this->getBindCarScore($item);
                    break;
                case CarExteriorRefitDefine::DB_ORNAMENTS:
                    $lightStrip = $this->getOrnamentsScore($item);
                    break;
                case CarExteriorRefitDefine::DB_TIRE:
                    $tire = $this->getNormalScore($item);
                    break;
                case CarExteriorRefitDefine::DB_NITROGEN:
                    $nitrogen = $this->getNormalScore($item);
                    break;
                case CarExteriorRefitDefine::DB_HUB:
                    $hub = $this->getNormalScore($item);
                    break;
                case CarExteriorRefitDefine::DB_LICENSE_IMAGE:
                    $licenseImage = $this->getNormalScore($item);
                    break;
//                case CarExteriorRefitDefine::DB_LICENCE:
//                    $licence = $this->getNormalScore($item);
//                    break;
                default:
                    break;
            }
        }
        // 外观累加数值
        $score = $skin + $paint + $tail + $hood + $sticker + $lightStrip + $ornaments
            + $tire + $nitrogen + $hub + $licenseImage + $licence;
        // 车的基础性能分
        $carData = $this->getCarByCarUID($uid);
        $carScore = 0;
        for($i = 1; $i <= $carData->level; $i ++) {
            $carAgg = $this->getCarAggrandizementID($carData->carID, $i);
            $carScore += $this->getTitle(TemplateDefine::TYPE_CAR_AGGRANDIZEMENT, $carAgg)
            [TemplateCarAggrandizement::Performance];
        }

        // 保存
        $carData->setPerformance($score + $carScore);
        $carData->saveDB();
        return true;
    }

    private function getNormalScore(string $val):int {
        if(empty($val)) {
            return 0;
        }
        return $this->getERScoreByUID($val);
    }

    private function getBindCarScore(string $val):int {
        if(empty($val)) {
            return 0;
        }
        $strArr = json_decode($val, true);
        foreach ($strArr as $item) {
            if($item[CarExteriorData::DB_IS_USE] === CarExteriorData::DB_EXTERIOR_TRUE) {
                return $this->getERScoreByUID($item[CarExteriorData::DB_UID]);
            }
        }
        return 0;
    }

    private function getStickerScore(string $val):int {
        if(empty($val)) {
            return 0;
        }
        $strArr = json_decode($val, true);
        $score = 0;
        foreach ($strArr as $item) {
            $score += $this->getERScoreByUID($item[CarExteriorData::DB_UID]);
        }
        return $score;
    }

    private function getOrnamentsScore(string $val):int {
        if(empty($val)) {
            return 0;
        }
        $arr = json_decode($val, true);
        return $this->getERScoreByUID($arr[CarExteriorData::DB_UID]);
    }

    private function getERScoreByUID(int $uid): int{
        $erData = new CarExteriorRefitData($this->playerId, $uid);
        $erData->searchExteriorRefit();
//        // 车牌号 返回0
//        if($erData->tplID === 0) {
//            return 0;
//        }
        $itemID =  $this->getTitle(TemplateDefine::TYPE_APPEARANCE, $erData->tplID)
        [TemplateAppearance::IDByItem];
        if(empty($itemID)) {
            return 0;
        }
        $itemCfg = $this->getTitle(TemplateDefine::TYPE_ITEM, $itemID);
        return $itemCfg[TemplateItem::ScoreNum];
    }

    private function getERItemIDByTplID(int $tplID): int {
        return (int)$this->getTitle(TemplateDefine::TYPE_APPEARANCE, $tplID)
        [TemplateAppearance::IDByItem];
    }

    private function initExteriorRefitPacket(CarExteriorRefitData $refit) {
        $this->exteriorRefit->setUID($refit->uid);
        $this->exteriorRefit->setTplID($refit->tplID);
        $this->exteriorRefit->setParams($refit->params);
        $this->exteriorRefit->setGetTime($refit->getTime);
        $this->exteriorRefit->setCarID($refit->carID);
    }

    public function sendPacket()
    {
        if (!empty($this->exteriorRefit)) {
            SendMessage::getInstance()->sendClient(PacketId::GC_SyncExteriorRefit, $this->exteriorRefit);
        }
    }

    private function appendAddExteriorRefitPacket(int $code) {
        $this->addExteriorRefit->setCode($code);
    }

    public function sendAddExteriorRefitPacket()
    {
        if (!empty($this->addExteriorRefit)) {
            SendMessage::getInstance()->sendClient(PacketId::GC_AddCarExteriorRefit, $this->addExteriorRefit);
        }
    }

    public function sendBindCarSyncPacket(CarExteriorData $car)
    {
        $this->bindCarSync->setUid($car->uid);
        $this->bindCarSync->setSkin($car->skin);
        $this->bindCarSync->setPaint($car->paint);
        $this->bindCarSync->setLightStrip($car->lightStrip);
        SendMessage::getInstance()->sendClient(PacketId::GC_SyncBindCarExteriorRefit, $this->bindCarSync);
    }

    //检查改装件id是否拥有
    public function checkExteriorRefitIdExist(int $id): bool
    {
        $arr = array();
        if(!$this->getTitleList(DBTableDefine::TABLE_EXTERIOR_REFIT, $this->playerId, $arr)) {
            return false;
        }
        if(empty($arr)) {
            return false;
        }
        return in_array($id, $arr);
    }
}
