<?php

/**
 * Login.php
 * 文件描述
 * Created On 2021/12/29
 * @author yuanb yuanbo0x@gmail.com
 */

namespace Game\Controller\Login;

use Framework\Define\ErrorDefine;
use Framework\Lib\Utils;
use Framework\Log\LogMark;
use Framework\MVC\ControllerBase;
use Framework\MVC\ModelManager;
use Framework\Network\SendMessage;
use Game\Config\GameConfig;
use Game\Constant\ClientErrorCode;
use Game\Constant\ConstTemplate\TemplateItem;
use Game\Constant\ConstTemplate\TemplateSeasonRewardCondition;
use Game\Constant\GameConstantDefine;
use Game\Constant\GameErrorCode;
use Game\Constant\ModelTypeDefine;
use Game\Data\AccountData;
use Game\Logic\AccountLogic;
use Game\Logic\ShieldWordsLogic;
use Game\Logic\Task\TaskLogic;
use Game\Model\ItemModel;
use Game\Protobuf\CGTestLogin;
use Game\Protobuf\GCGetServerState;
use Game\Protobuf\GCSyncBanPlayer;
use Game\Protobuf\GCTestLogin;
use Game\Protobuf\PacketId;
use Tool\InitServer\Config;
use Game\Logic\CommonConstLogic;

class LoginTest extends ControllerBase
{
    use AccountLogic;
    use CommonConstLogic;
    use AccountLogic;
    use ShieldWordsLogic;
    use TaskLogic;

    private GCTestLogin $sendMessage;

    public function __construct()
    {
        $this->message = new CGTestLogin();
        $this->sendMessage = new GCTestLogin();
    }

    public function run(): int
    {
        $account = $this->message->getAccount();
        $this->playerId = $this->searchPlayerIdByAccount($account);
        $sessionId = $this->makeSessionId();
        $isRegister = false;

        if ($this->playerId == 0) {
            $type = $this->message->getAccountType();
            $passWord = $this->message->getPassword();
            $deviceID = $this->message->getDeviceID();
            $isRegister = true;
            $this->playerId = $this->makePlayerId();
            $this->register($account, $this->playerId, $type, $passWord, $deviceID, $this->message->getClientData());
            $nickName = $this->message->getNickName();
            $carID = $this->message->getCarTplID();
            $itemID = $this->message->getItemID();
            $this->selectMod(GameConstantDefine::roleSelectModel, $this->message->getModelID());
            $this->inputName(GameConstantDefine::roleInputName, $nickName);
            $this->selectCar(GameConstantDefine::roleSelectCar, $carID, $itemID);
            $this->guideStepOver(GameConstantDefine::STEP_COMPLETE);
        }
        ModelManager::getInstance()->setPlayerId($this->playerId);
        $accountType = $this->getAccountProperty($this->playerId, AccountData::DB_ACCOUNT_TYPE);
        if(is_null($accountType)) {
            $accountType = AccountData::PLAYER_GM;
        }

        $this->saveLoginSessoin($this->playerId, $sessionId);
        switch ($accountType) {
            case AccountData::PLAYER_NORMAL:
                // 服务器状态
                if(!$this->checkServerState()) {
                    return ErrorDefine::SUCCESS;
                }
                // 封号
                if(!$this->checkBanPlayer()) {
                    return ErrorDefine::SUCCESS;
                }
                break;
            case AccountData::PLAYER_GUEST:
                // 服务器状态
                if(!$this->checkServerState()) {
                    return ErrorDefine::SUCCESS;
                }
                // 封号
                if(!$this->checkBanPlayer()) {
                    return ErrorDefine::SUCCESS;
                }
                // 校验密码
                if(!$this->checkLoginPassword()) {
                    $this->sendLoginMsg(ClientErrorCode::LOGIN_PASSWORD_NOT_EQUAL_ERROR);
                    return ErrorDefine::SUCCESS;
                }
                break;
            case AccountData::PLAYER_GM:
//                // 校验密码  走之前逻辑 不校验密码
//                if(!$this->checkLoginPassword()) {
//                    $this->sendLoginMsg(ClientErrorCode::LOGIN_PASSWORD_NOT_EQUAL_ERROR, $sessionId);
//                    return ErrorDefine::SUCCESS;
//                }
                break;
        }
        $clientData = $this->message->getClientData();
        $this->login($this->playerId, $isRegister, $clientData);
        $this->sendLoginMsg(ClientErrorCode::CLIENT_SUCCESS);
        return ErrorDefine::SUCCESS;
    }

    //选择模型
    private function selectMod(int $step, int $modelID)
    {
        $this->saveAccountModel($step, $modelID);
    }

    private function inputName($step, $nickName):bool {
        //检查敏感词
        if ($this->checkFuckWord($nickName)) {
            $this->sendMessage->setCode(ClientErrorCode::NICKNAME_HAS_SHIELD_WORD);
            SendMessage::getInstance()->sendClient(PacketId::GC_TestLogin, $this->sendMessage);
            return ErrorDefine::SUCCESS;
        }
        //检查昵称长度
        $code = $this->checkNicknameLen($nickName);
        if ($code != ClientErrorCode::CLIENT_SUCCESS) {
            $this->sendMessage->setCode($code);
            SendMessage::getInstance()->sendClient(PacketId::GC_TestLogin, $this->sendMessage);
            return ErrorDefine::SUCCESS;
        }
        //检测RoleName是否可用
        if (!$this->checkRoleName($nickName)) {
            $this->sendMessage->setCode(ClientErrorCode::CLIENT_SUCCESS);
            SendMessage::getInstance()->sendClient(PacketId::GC_TestLogin, $this->sendMessage);
            return false;
        }

        if (!$this->saveAccountName($step, $nickName)) {
            LogMark::getInstance()->markError(GameErrorCode::CREATE_ROLE_ERROR,
                '[InputName] save name error!');
            $this->sendMessage->setCode(ClientErrorCode::ACCOUNT_CREATE_NAME_ERROR);
            SendMessage::getInstance()->sendClient(PacketId::GC_TestLogin, $this->sendMessage);
            return false;
        }
        return true;
    }

    private function selectCar($step, $carID, $itemID): bool {
        $carUid = $this->createSystemCar($carID, $itemID);
        if ($carUid == false)
        {
            $this->sendMsg(ClientErrorCode::ACCOUNT_SELECT_CAR_ERROR);
            return false;
        }
        $data = [
            AccountData::DB_STEP => $step,
            AccountData::DB_DEFAULT_CAR => $carUid,
            AccountData::DB_DEFAULT_CAT_TPL => $carID
        ];

        if (!$this->saveAccountData($data)) {
            LogMark::getInstance()->markError(
                GameErrorCode::UPDATE_ROLE_ERROR,
                '[control] update account data error!');
            $this->sendMsg(ClientErrorCode::ACCOUNT_SELECT_CAR_ERROR);
            return false;
        }
        $this->sendMsg(ClientErrorCode::CLIENT_SUCCESS);

        //创建角色完成 初始任务
        $this->initTaskOnRegisterOver();

        // 选车车辆排行榜更新
        $this->addCarRefitRank(0, $itemID, TemplateItem::TYPE_CAR);

        // 注册角色完成 初始化信息
        $this->initPlayerData();
        //更新好友分
        $this->updateRandomScore();
        $roleModel = $this->getAccountAttribute(AccountData::DB_ROLE_MODEL_ID);
        // 发送货币 衣服 车
        /**
         * @var ItemModel $itemModel
         */
        $itemModel = ModelManager::getInstance()->getModel(ModelTypeDefine::ITEM);
        $itemModel->initPlayerItemData($roleModel);

        return ErrorDefine::SUCCESS;
    }

    private function guideStepOver(int $step)
    {
        $data = [
            AccountData::DB_STEP => $step,
        ];
        $this->saveAccountData($data);
    }

    private function sendMsg(int $code)
    {
        $this->sendMessage->setCode($code);
        SendMessage::getInstance()->sendClient(PacketId::GC_TestLogin, $this->sendMessage);
    }

    private function sendLoginMsg(int $code) {
        $this->sendMessage->setCode($code);
        SendMessage::getInstance()->sendClient(PacketId::GC_TestLogin, $this->sendMessage);
    }

    private function checkLoginPassword():bool {
        $passWord = $this->message->getPassword();
        $password = $this->getAccountProperty($this->playerId, AccountData::DB_PASSWORD_MD5);
        if(is_null($password)) {
            return false;
        }
        if($password != md5($passWord)) {
            return false;
        }
        return true;
    }

    private function checkServerState():bool {
        $msg = new GCGetServerState();
        $result = $this->getCommonConstData();
        if(!isset($result[Config::SERVER_STATE_KEY])) {
            $msg->setCode(ClientErrorCode::SERVER_STATE_SEARCH_NOT_FOUND_ERROR);
        } else {
            if($result[Config::SERVER_STATE_KEY] != Config::SERVER_TYPE_OPENING) {
                $time_str = GameConfig::getInstance()->OPEN_SERVER_TIME();
                $time_s = strtotime($time_str);
                $msg->setCode(ClientErrorCode::CLIENT_SUCCESS);
                $msg->setStartTime($time_s);
                $msg->setState((int)$result[Config::SERVER_STATE_KEY]);
            } else {
                return true;
            }
        }
        SendMessage::getInstance()->sendClient(PacketId::GC_GetServerState, $msg);
        return false;
    }

    // 检测封号
    private function checkBanPlayer():bool {
        $banTime = $this->getAccountProperty($this->playerId, AccountData::DB_BAN_TIME);
        // 没有被封号过
        if(is_null($banTime) || empty($banTime)) {
            return true;
        }
        $time = Utils::getServerTimestamp();
        // 已经解封
        if($time > $banTime) {
            return true;
        }
        $msg = new GCSyncBanPlayer();
        $msg->setCode(ClientErrorCode::CLIENT_SUCCESS);
        $msg->setTime($banTime);
        SendMessage::getInstance()->sendClient(PacketId::GC_SyncBanPlayer, $msg);
        return false;
    }

}
