<?php

namespace Tournament;

use Core\Db;

class Tournament
{
    const IS_ENABLED = false;
    private const SEND_CHAT_MESSAGE = 3;
    public const START_TOURNAMENT = 5;
    private const PRIZE1 = 25;
    private const PRIZE2 = 10;
    private const PRIZE3 = 5;
    const MIN_EXP = 175000;
    private const CHAT_MESSAGE = 'Внимание! Турнир для %d уровня открыт! Поспешите принять участие в Зале Воинов!';
    private const VICTORY_MESSAGE = 'Турнир для %d уровней завершён! Первое место: %s. Второе место: %s. Третье место: %s.';
    private const DELAY1 = '+12hour';
    private const DELAY2 = '+6hour';
    private const DELAY3 = '+3hour';

    /** Формула рассчёта разрешённой стоимости одетых предметов.
     *
     * @param int $int
     *
     * @return float|int
     */
    public static function ekrOverpriceFormula(int $int): int
    {
        return ($int - 7) * 151;
    }

    /**
     * Проверяем может ли игрок учавствовать в турнире и либо присоединяем его, либо обламываем.
     *
     * @param int $uid
     *
     * @return void
     */
    public function join(int $uid): void
    {
        /** Возвращает level, или 0 если провалены проверки. */
        $userLevel = TournamentModel::getUserLevel($uid);
        if (
            $userLevel === 0 ||
            TournamentModel::isEkrOverpriced($uid, $userLevel) ||
            !TournamentModel::isEnoughExperience($uid) ||
            TournamentModel::isRestrictedToJoin($uid) ||
            TournamentModel::isStarted($uid)
        ) {
            return;
        }

        $mq = TournamentModel::getWaitingMembersQuantity($userLevel);
        if (empty($mq)) {
            TournamentModel::createTournament($userLevel);
        }

        TournamentModel::joinTournament($uid, $userLevel);
        $mq++;

        if ($mq == self::SEND_CHAT_MESSAGE) {
            TournamentModel::sysMessage(sprintf(self::CHAT_MESSAGE, $userLevel));
        }

        if ($mq == self::START_TOURNAMENT) {
            TournamentModel::startTournament($userLevel);
        }
    }

    /**
     * Проверка для крона\конфига. Выбивает проигравших и перезапускает поединки во всех турнирах.
     * @return void
     */
    public function startAllBattles(): void
    {
        Db::sql(
            'delete from tournaments where start_time + date_add(start_time,interval 30 minute) < unix_timestamp()'
        );
        TournamentModel::removeFighter(TournamentModel::getLooser());
        $tournamentLevels = Db::getColumn('select tid from tournaments where start_time = -1');
        foreach ($tournamentLevels as $level) {
            $aliveFighters = TournamentModel::getFreeFighters($level);
            if (count($aliveFighters) > 1) {
                shuffle($aliveFighters);
                $this->startBattle($aliveFighters);
            } elseif (count($aliveFighters) === 1) {
                TournamentModel::removeFighter($aliveFighters[0], true);
                $this->victory($level);
            }
        }
    }

    /**
     * Получаем пары бойцов и начинаем их поединки.
     *
     * @param array $fightersList
     *
     * @return void
     */
    private function startBattle(array $fightersList): void
    {
        $teams = TournamentModel::getFightersTeams($fightersList);
        foreach ($teams as $team) {
            if (count($team) === 2) {
                TournamentModel::startBattle($team[0], $team[1]);
            }
        }
    }

    /**
     * Награждаем победителей турнира, чистим базу.
     *
     * @param int $tid
     *
     * @return void
     */
    private function victory(int $tid): void
    {
        $winners = TournamentModel::getWinners($tid);
        sleep(1);
        TournamentModel::givePrizeItems($winners[1], self::PRIZE1);
        TournamentModel::givePrizeItems($winners[2], self::PRIZE2);
        TournamentModel::givePrizeItems($winners[3], self::PRIZE3);
        sleep(1);
        TournamentModel::giveDelay($winners[1], strtotime(self::DELAY1));
        TournamentModel::giveDelay($winners[2], strtotime(self::DELAY2));
        TournamentModel::giveDelay($winners[3], strtotime(self::DELAY3));
        sleep(1);
        TournamentModel::sysMessage(
            sprintf(
                self::VICTORY_MESSAGE,
                $tid,
                TournamentModel::uidToLogin($winners[1]),
                TournamentModel::uidToLogin($winners[2]),
                TournamentModel::uidToLogin($winners[3])
            )
        );
        sleep(3);
        TournamentModel::destroyTournament($tid);
    }
}