<?php
# Date: 12.02.2022 (20:33)
namespace Battles;

use Battles\Database\Db;

class Arena
{
    private int $fight_id;
    private int $team_id;

    function addNew(int $membersLimit = 5, int $groupsLimit = 2, int $startTime = 3)
    {
        if (
            $this->isOnArena() &&
            $this->hasNoPendingFights() &&
            $this->hasNoActiveFights() &&
            in_array($startTime, [1,3,5,10])
        ) {
            $query1 = 'insert into fights_pending (fight_id, start_time, members_limit, groups_limit) VALUES (?,?,?,?)';
            $query2 = 'insert into fights_pending_users (fight_id, user_id, team_id) values (?,?,?)';
            $startTime = strtotime("+{$startTime}minutes");
            $uid = User::getInstance()->getId();
            //последовательность важна!
            Db::getInstance()->execute($query1, [$uid, $startTime, $membersLimit, $groupsLimit]);
            Db::getInstance()->execute($query2, [$uid, $uid, 1]);
        }
    }

    function join(int $fight_id, int $team_id)
    {
        $this->fight_id = $fight_id;
        $this->team_id = $team_id;
        if (
            $this->hasNoClanEnemies() &&
            $this->hasFreeSpace() &&
            $this->isOnArena() &&
            $this->hasNoPendingFights() &&
            $this->hasNoActiveFights()
        ) {
            $query = 'insert into fights_pending_users (fight_id, user_id, team_id) values (?,?,?)';
            Db::getInstance()->execute($query, [$fight_id, User::getInstance()->getId(), $team_id]);
        }
    }

    function leave()
    {
        // чтобы не вылететь из заявки в момент начала поединка
        if (
            $this->hasNoActiveFights() &&
            !$this->isFightStarter()
        ) {
            Db::getInstance()->execute('delete from fights_pending_users where user_id = ?', User::getInstance()->getId());
        }
    }

    function getPendingList(): object
    {
        return new \stdClass();
        /** !!PLACEHOLDER!! */
    }

    public static function fight(): self
    {
        return new self();
    }

    // проверка на соклана
    private function hasNoClanEnemies(): bool
    {
        $query = 'select user_id from fights_pending_users where fight_id = ? and team_id = ?';
        $enemies = Db::getInstance()->ofetchAll($query, [$this->fight_id, $this->team_id]);
        foreach ($enemies as $enemy) {
            if (User::getInstance()->getClan() && User::getInstance()->getClan() === User::getInstance($enemy->user_id)->getClan()) {
                return false;
            }
        }
        return true;
    }

    // проверка на переполнение
    private function hasFreeSpace(): bool
    {
        $query = 'select members_limit, groups_limit from fights_pending where fight_id = ?';
        $query2 = 'select count(*) from fights_pending_users where fight_id = ? and team_id = ?';
        $limits = Db::getInstance()->ofetch($query, $this->fight_id);
        $currentUsers = Db::getInstance()->fetchColumn($query2, [$this->fight_id, $this->team_id]);
        return $limits->members_limit > $currentUsers && $limits->groups_limit >= $this->team_id;
    }

    // проверка на нахождение в комнате (1 = арена)
    private function isOnArena(): bool
    {
        return User::getInstance()->getRoom() === 1;
    }

    // проверка на нахождение в другой заявке
    public function hasNoPendingFights(): bool
    {
        $query = 'select count(*) from fights_pending_users where user_id = ?';
        return Db::getInstance()->fetchColumn($query, User::getInstance()->getId()) > 0;
    }

    // проверка на нахождение в поединке
    public function hasNoActiveFights(): bool
    {
        $query = 'select count(*) from fighters where user_id = ?';
        return Db::getInstance()->fetchColumn($query, User::getInstance()->getId()) > 0;
    }

    // проверка на создателя поединка
    private function isFightStarter(): bool
    {
        $query = 'select count(*) from fights_pending_users where user_id = fight_id and user_id = ?';
        return Db::getInstance()->fetchColumn($query, User::getInstance()->getId()) > 0;
    }
}