<?php
/**
 * 房间数据类
 */
namespace Game\Data;

use Framework\Lib\Utils;
use Framework\Log\LogMark;
use Game\Constant\DBTableDefine;
use Framework\DB\Handler\PlayerDBHandler;
use Game\Constant\GameErrorCode;
use Game\Data\PaiWei\PaiweiLevelData;

class RoomData {
    use PlayerDBHandler;

    // room
    public const ROOM_ID     = "RoomID";
    public const ROOM_NAME   = "RoomName";
    public const ROOM_STATE  = "RoomState";
    public const MAP_ID      = "MapID";
    public const MODE_TYPE   = "ModeType";
    public const PLAYER_INFO = "PlayerInfo";
    public const PLAY_TYPE   = "PlayType";
    public const INVITED_INFO1 = "InvitedInfo1";    //邀请信息 [邀请人id=>[被邀请人,..]]
    public const INVITED_INFO2 = "InvitedInfo2";    //被邀请信息 [被邀请人=>邀请人]
    public const CHAT_ID = "ChatID";

    // player
    public const JOIN_TIME   = "JoinTime";
    public const READY_STATE = "ReadyState";
    public const PLAYER_ID   = "PlayerID";
    //赛车信息
    public const CAR_TPL_ID  = "CarTplID";
    public const EXTERIOR_REFIT = "ExteriorRefit";
    public const PROFICIENCY = "Proficiency";      //熟练度
    public const PROFICIENCY_LV = "ProficiencyLv";      //熟练度等级
    public const CAR_LV = "CarLv";      // 车等级
    //玩家信息
    public const GENDER = "Gender";
    public const CLOTH = "Cloth";
    public const HEAD = "Head";
    public const NICK_NAME = "NickName";
    public const POSITION = "Position"; //显示位置 0随机1竞速位2干扰位3辅助位
    public const SCUFFLE_SCORE = "ScuffleScore";    //大乱斗积分
    public const CONTINUITY_WIN = "continuityWin";  //连胜次数
    public const PLAYER_LEVEL = "PlayerLevel";  //玩家等级
    public const PLAYER_DAN = "PlayerDan";      //玩家段位

    public const DB_KEY_MAP = array(
        self::ROOM_ID     => "roomID",
        self::ROOM_NAME   => "roomName",
        self::ROOM_STATE  => "roomState",
        self::MAP_ID      => "mapID",
        self::MODE_TYPE   => "modeType",
        self::PLAYER_INFO => "playerInfo",
        self::PLAY_TYPE   => "playType",
        self::INVITED_INFO1 => "invitedInfo1",
        self::INVITED_INFO2 => "invitedInfo2",
        self::CHAT_ID => "chatID"
    );

    public int    $playerID = 0;
    public int    $roomID;
    public string $roomName;
    public int    $roomState;   // 房间状态  1私人 2公开
    public int    $mapID;       // 地图id
    public int    $modeType;    // 模式类型
    public array  $playerInfo;  // 房间内玩家信息
    public int    $playType;    // 游戏类型  1准备 2游戏 3结算
    public string $invitedInfo1;
    public string $invitedInfo2;
    public string    $chatID = ""; // 聊天ID

    public function __construct(
        int $roomID, int $playerID = 0, string $roomName = '', int $roomState = 1, int $mapID = 0,
        int $modeType = 0, array $playerInfo = [], int $playType = 1, string $chatID = ""
    ) {
        $this->roomID     = $roomID;
        $this->playerID   = $playerID;
        $this->roomName   = $roomName;
        $this->roomState  = $roomState;
        $this->mapID      = $mapID;
        $this->modeType   = $modeType;
        $this->playerInfo = $playerInfo;
        $this->playType   = $playType;
        $this->invitedInfo1 = "[]";
        $this->invitedInfo2 = "[]";
        $this->chatID = $chatID;
    }

    public function playerCreateRoomDB(int $playerID, int $carTplID): ?int {

        // 分数   matchType*10000 + state * 1000 + type * 100 + num
        // 因为是新建 所以 以上参数全部为 1
        $score = 11101;

        $data = [
            'roomID' => (int)$this->roomID,
            'roomName' => $this->roomName,
            'mapID' => (int)$this->mapID,
            'modeType' => (int)$this->modeType,
            'playerID' => $playerID,
            'carTplID' => $carTplID,
            'time' => Utils::getServerTimestamp(),
            'score' => (int)$score,
            'exteriorRefit' => $this->playerInfo[$this->playerID][self::EXTERIOR_REFIT],
            //对应 CreateRoom.lua 参数索引顺序,加新参数同步修改参数数量校验
            10 => $this->playerInfo[$this->playerID][self::PROFICIENCY],
            11 => $this->playerInfo[$this->playerID][self::PROFICIENCY_LV],
            12 => $this->playerInfo[$this->playerID][self::GENDER],
            13 => $this->playerInfo[$this->playerID][self::CLOTH],
            14 => $this->playerInfo[$this->playerID][self::HEAD],
            15 => $this->playerInfo[$this->playerID][self::NICK_NAME],
            16 => $this->playerInfo[$this->playerID][self::POSITION],
            17 => $this->playerInfo[$this->playerID][self::SCUFFLE_SCORE],
            18 => $this->playerInfo[$this->playerID][self::CONTINUITY_WIN],
            19 => $this->playerInfo[$this->playerID][AccountData::DB_SKIN_COLOR],
            20 => $this->playerInfo[$this->playerID][self::CAR_LV],
            21 => $this->chatID,
            22 => $this->playerInfo[$this->playerID][self::PLAYER_LEVEL],
            23 => $this->playerInfo[$this->playerID][self::PLAYER_DAN],
        ];

        return $this->createRoomDB(DBTableDefine::TABLE_ROOM, 0, $this->roomID, $data);
    }

    public function playerJoinRoomDB(int $maxNum, int $playerID, array $showPlayer, array $showCar): ?int {

        $data = [
            'maxNum' => intval($maxNum),
            'playerID' => $playerID,
            'carTplID' => $showPlayer[self::CAR_TPL_ID],
            'time' => Utils::getServerTimestamp(),
            'exteriorRefit' => $showCar[self::EXTERIOR_REFIT],
            //对应 JoinRoom.lua 参数索引顺序,加新参数同步修改参数数量校验
            6 => $showCar[self::PROFICIENCY],
            7 => $showCar[self::PROFICIENCY_LV],
            8 => $showPlayer[self::GENDER],
            9 => $showPlayer[self::CLOTH],
            10 => $showPlayer[self::HEAD],
            11 => $showPlayer[self::NICK_NAME],
            12 => $showPlayer[self::POSITION],
            13 => $showPlayer[self::SCUFFLE_SCORE],
            14 => $showPlayer[self::CONTINUITY_WIN],
            15 => $showPlayer[AccountData::DB_SKIN_COLOR],
            16 => $showCar[self::CAR_LV],
            17 => $showPlayer[self::PLAYER_LEVEL],
            18 => $showPlayer[self::PLAYER_LEVEL],
        ];

        return $this->joinRoom(DBTableDefine::TABLE_ROOM, 0, $this->roomID, $data);
    }

    public function playerExitRoomDB(int $roomID, int $eID): ?int {

        $data = [
            'roomID' => $roomID,
            'exitID' => $eID,
        ];

        return $this->exitRoomDB(DBTableDefine::TABLE_ROOM, 0, $this->roomID, $data);
    }

    public function saveDB(): bool
    {
        $data = array();
        foreach (self::DB_KEY_MAP as $k => $v) {
            if($k == self::PLAYER_INFO) {
                $data[$k] = json_encode($this->$v);
            } else {
                $data[$k] = $this->$v;
            }
        }

        if(!$this->updateTitle(DBTableDefine::TABLE_ROOM, 0, $this->roomID, $data)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[data] room update error!', $data
            );
            return false;
        }
        $roomNum = count($this->playerInfo);
        $score = $this->modeType * 10000 + $this->roomState * 1000 + $this->playType * 100 + $roomNum;
        if(!$this->addRank(DBTableDefine::TABLE_ROOM, 0, $this->roomID, $score)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[data] room update z set error!', $data
            );
            return false;
        }
        return true;
    }

    public function deleteRoom(): bool {

        if(!$this->deleteTitle(DBTableDefine::TABLE_ROOM, 0, $this->roomID)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_DELETE_ERROR,
                '[data] room delete error!',
                ['playerID' => $this->playerID, 'uid' => $this->roomID]
            );
            return false;
        }
        return true;
    }

    // 查找房间
    public function searchRoomByRoomID(): bool {
        $room = [];
        if(!$this->searchTitle(DBTableDefine::TABLE_ROOM, 0, $this->roomID, $room)) {
            LogMark::getInstance()->markError(GameErrorCode::DATA_SEARCH_ERROR,
                'search room info error!');
            return false;
        }

        if(empty($room)) {
            return false;
        }
        $this->setRoomName($room[self::ROOM_NAME]);
        $this->setRoomState($room[self::ROOM_STATE]);
        $this->setMapID($room[self::MAP_ID]);
        $this->setModeType($room[self::MODE_TYPE]);
        $this->setPlayType($room[self::PLAY_TYPE]);
        $this->setRoomPlayerInfo($room[self::PLAYER_INFO]);
        if (isset($room[self::CHAT_ID])) {
            $this->setChatID($room[self::CHAT_ID]);
        } else {
            $this->setChatID("");
        }
        if (isset($room[self::INVITED_INFO1])) {
            $this->setInvitedInfo($room[self::INVITED_INFO1], $room[self::INVITED_INFO2]);
        } else {
            $this->setInvitedInfo("[]", "[]");
        }
        return true;
    }

    public function setRoomID(int $roomID) {
        $this->roomID = $roomID;
    }

    public function setRoomName(string $roomName) {
        $this->roomName = $roomName;
    }

    public function setRoomState(int $roomState) {
        $this->roomState = $roomState;
    }

    public function setMapID(int $mapID) {
        $this->mapID = $mapID;
    }

    public function setModeType(int $modeType) {
        $this->modeType = $modeType;
    }

    public function setPlayType(int $playType) {
        $this->playType = $playType;
    }

    public function setChatID(string $chatID) {
        $this->chatID = $chatID;
    }

    public function setRoomPlayerInfo(string $info) {
        $this->playerInfo = json_decode($info, true);
    }

    public function setPlayerCar(array &$player,int $carID, array $showCar) {
        $player[self::CAR_TPL_ID] = $carID;
        $player[self::EXTERIOR_REFIT] = $showCar[self::EXTERIOR_REFIT];
        $player[self::PROFICIENCY_LV] = $showCar[self::PROFICIENCY_LV];
        $player[self::PROFICIENCY] = $showCar[self::PROFICIENCY];
        $player[self::CAR_LV] = $showCar[self::CAR_LV];
    }

    public function setPlayerShow(array &$player, array $showPlayer) {
        $player[self::SCUFFLE_SCORE] = $showPlayer[self::SCUFFLE_SCORE];
        $player[self::CONTINUITY_WIN] = $showPlayer[self::CONTINUITY_WIN];
        $player[self::PLAYER_LEVEL] = $showPlayer[self::PLAYER_LEVEL];
        $player[self::PLAYER_DAN] = $showPlayer[self::PLAYER_DAN];
    }

    public function setPlayerState(array &$player,int $state) {
        $player[self::READY_STATE] = $state;
    }

    public function setInvitedInfo(string $invitedInfo1, string $invitedInfo2)
    {
        $this->invitedInfo1 = $invitedInfo1;
        $this->invitedInfo2 = $invitedInfo2;
    }

    public function setPlayerPosition(array &$player, int $position) {
        $player[self::POSITION] = $position;
    }

    public function setPlayerCloth(array &$player, string $cloth)
    {
        $player[self::CLOTH] = $cloth;
    }

    public function saveInvitedInfo(): bool
    {
        $data = array(
            self::INVITED_INFO1 => $this->invitedInfo1,
            self::INVITED_INFO2 => $this->invitedInfo2
        );
        if(!$this->updateTitle(
            DBTableDefine::TABLE_ROOM,
            0,
            $this->roomID,
            $data)
        ) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[RoomData] update invited info error!', $data
            );
            return false;
        }
        return true;
    }
}