<?php

/**
 * 大乱斗房间
 */

namespace Game\Model\Room;

use Framework\DB\Handler\PlayerDBHandler;
use Framework\Lib\Utils;
use Framework\Log\LogMark;
use Framework\Logic\PacketCacheLogic;
use Framework\Network\SendMessage;
use Game\Constant\GameErrorCode;
use Game\Data\JoinIdData;
use Game\Data\Room\ScuffleRoomData;
use Game\Logic\AccountLogic;
use Game\Logic\GenerateAiLogic;
use Game\Logic\RecordLogic;
use Game\Protobuf\GCBroadcastScuffleRoomPlayer;
use Game\Protobuf\GCBroadcastScuffleRoomPublicPool;
use Game\Protobuf\PacketId;
use Game\Protobuf\PlayerInfo;
use Game\Protobuf\PublicPool;

class ScuffleRoomModel
{
    use AccountLogic;
    use RecordLogic;
    use PacketCacheLogic;
    use GenerateAiLogic;

    use PlayerDBHandler;

    public int $playerId;

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

    public function getPlayerId(): int
    {
        return $this->playerId;
    }

    public function createRoom(array $data): bool
    {
        $scuffleRoomData = new ScuffleRoomData($data[ScuffleRoomData::ROOM_ID]);
        if (false == $scuffleRoomData->createRoom($data)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                "[ScuffleRoomModel] create room error",
                $data
            );
            return false;
        }
        if (false == $scuffleRoomData->createRoomTime()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_CREATE_ERROR,
                "[ScuffleRoomModel] create room time error",
                $data
            );
            return false;
        }
        return true;
    }

    public function getScuffleRoomDataByJoinId(): ?array
    {
        $joinId = $this->getAccountProperty($this->playerId, JoinIdData::JOIN_ID, 0);
        if (empty($joinId)) {
            LogMark::getInstance()->markDebug(
                "[ScuffleRoomModel] getScuffleRoomDataByJoinId not found player joinId"
            );
            return null;
        }
        $record = $this->getRecordByJoinId($joinId);
        if (is_null($record)) {
            LogMark::getInstance()->markDebug(
                "[ScuffleRoomModel] getScuffleRoomDataByJoinId not found player record",
                array(
                    "joinId" => $joinId
                )
            );
            return null;
        }
        return (new ScuffleRoomData($record->matchUID))->searchScuffleRoom();
    }

    //记录申请信息
    public function markApplyInfo(int $roomId, int $applyPlayerId, int $targetPlayerId, array $data): bool
    {
        $data[ScuffleRoomData::APPLY_TIME] = Utils::getServerTimestamp();
        $data[$targetPlayerId] = ScuffleRoomData::APPLY_RESULT_STATUS_WAIT;
        $data[ScuffleRoomData::APPLY_STATUS] = ScuffleRoomData::APPLY_STATUS_WAIT;

        $tarData[ScuffleRoomData::APPLY_TIME] = 0;
        $tarData[$applyPlayerId] = ScuffleRoomData::APPLY_RESULT_STATUS_WAIT;
        $tarData[ScuffleRoomData::APPLY_STATUS] = ScuffleRoomData::APPLY_STATUS_WAIT;
        $info = array(
            $applyPlayerId. "#" . ScuffleRoomData::APPLY_KEY => json_encode($data),
            $targetPlayerId . "#" . ScuffleRoomData::APPLY_KEY => json_encode($tarData),
        );
        return $this->updateScuffleRoom($roomId, $info);
    }

    public function updateScuffleRoom(int $roomId, array $data): bool
    {
        return (new ScuffleRoomData($roomId))->saveRoom($data);
    }

    //广播房间内赛车变化--给房间内所有人
    public function broadcastPlayerCarChange(PlayerInfo $playerInfo, array $roomKeys, int $changePlayerId)
    {
        $message = new GCBroadcastScuffleRoomPlayer();
        $message->setPlayerId($playerInfo->getPlayerId());
        $message->setCarTplId($playerInfo->getCarTplId());
        $message->setExteriorRefit($playerInfo->getExteriorRefit());
        $message->setProficiencyLv($playerInfo->getProficiencyLv());
        $message->setProficiency($playerInfo->getProficiency());
        foreach ($roomKeys as $key) {
            if (is_numeric($key) && !$this->checkIsAIPlayer($key)) {
                $this->addPacket(PacketId::GC_BroadcastScuffleRoomPlayer, $message, $key);
            }
        }
    }

    //广播公共车池变化--只给同队人
    public function broadcastPublicCarPoolChange(int $groupId, array $publicCarPool, array $scuffleRoomData)
    {
        $poolMessage = $this->markPublicCarPoolMessage($publicCarPool);
        $message = new GCBroadcastScuffleRoomPublicPool();
        $message->setPool($poolMessage);
        foreach ($scuffleRoomData as $pId => $data) {
            if (is_numeric($pId) && !$this->checkIsAIPlayer($pId)) {
                $playerInfo = new PlayerInfo();
                $playerInfo->mergeFromJsonString($data);
                if ($playerInfo->getGroupID() == $groupId) {
                    $this->addPacket(PacketId::GC_BroadcastScuffleRoomPublicPool, $message, $pId);
                }
            }
        }
    }

    private function markPublicCarPoolMessage(array $publicCarPool): array
    {
        $message = array();
        for ($i = 1; $i <= 6; $i++) {
            $key = (string)$i;
            $pool = new PublicPool();
            $pool->setIndex($i);
            $pool->setCarTplId($publicCarPool[$key][ScuffleRoomData::CAR_ID]);
            $pool->setCd($publicCarPool[$key][ScuffleRoomData::POOL_CD]);
            $message[] = $pool;
        }
        return $message;
    }

    //处理超时大乱斗房间,并删除
    public function dealOverTimeScuffleRoom()
    {
        //查询超时房间
        $rooms = (new ScuffleRoomData(0))->getOverTimeScuffleRoom();
        foreach ($rooms as $roomId => $time) {
            $room = new ScuffleRoomData($roomId);
            $room->delRoom();
            $room->delRoomTime();
        }
    }
}
