<?php

class User
{
    public $id = 0;
    public $login = '<em>Некто</em>';
    public $pass;
    public $email = '<em>неизвестно</em>';
    public $realname;
    public $borndate;
    public $info;
    public $level = 0;
    public $align = 0;
    public $clan = 0;
    public $money = 0;
    public $strength = 0;
    public $dexterity = 0;
    public $intuition = 0;
    public $endurance = 0;
    public $intelligence = 0;
    public $wisdom = 0;
    public $health;
    public $mana;
    public $ip;
    public $session_id;
    public $admin = 0;
    public $enter_game;
    public $room;
    public $block;
    public $shadow;
    // Удар кулаком всегда 1-2.
    public $minDamage = 1;
    public $maxDamage = 2;
    //Броня без предметов не существует.
    public $headArmor = 0;
    public $chestArmor = 0;
    public $legArmor = 0;
    public $free_stat_points = 0;
    public const STAT_MAXIMUM_AMOUNT = 40;
    private const ERROR_STAT_IS_MAXIMUM = 'Ошибка: Параметр достиг своего лимита!';
    private const ERROR_STAT_UNKNOWN = 'Ошибка: Неизвестный параметр!';
    // Пока несуществующие, для совместимости.
    public $married = 'Someone или нет.';
    public $experience = 200;
    public $battle = 0;
    public $in_tower = 0; // Скорее башню похороним чем запустим...
    public $zayavka = 0;
    // Динамически рассчитываемые
    public $maxHealth = 5;
    public $maxMana = 5;
    //Статусы того, кто смотрит на информацию.
    public $watcher_id;
    protected $watcherIsAdmin;
    protected $watcherIsModerator;

    use Rooms;

    public function __construct($user)
    {
        $user_query = db::c()->query('SELECT * FROM users WHERE id = "?s" OR login = "?s"', $user, $user)->fetch_assoc();
        foreach ($this as $key => $value) {
            if (isset($user_query[$key])) {
                $this->$key = $user_query[$key];
            }
        }
        $this->maxHealth = round(($this->endurance * 3) + ($this->endurance / 2) * ($this->level - 1) + ($this->endurance / 5) * (($this->level - 1) * ($this->level - 2) / 2));
        $this->maxMana = round(($this->wisdom * 3) + ($this->wisdom / 2) * ($this->level - 1) + ($this->wisdom / 5) * (($this->level - 1) * ($this->level - 2) / 2));
    }

    /**
     * Отдаёт информацию о базовом(!) стате.
     * @param     $stat_name    - имя стата. Может принимать значения 'strength', 'dexterity', 'intuition', 'endurance', 'intelligence', 'wisdom'.
     * @param int $isMainWindow - переключатель "главного окна". Если включить, дополнительно будет показывать ссылку на повышение стата на 1, при условии наличия свободных очков статов.
     * @return string
     * @throws Exception
     */
    public function getStat($stat_name, $isMainWindow = 0)
    {
        $allowed = ['strength', 'dexterity', 'intuition', 'endurance', 'intelligence', 'wisdom'];
        if (in_array($stat_name, $allowed)) {
            if ($this->free_stat_points && $isMainWindow && $this->$stat_name < self::STAT_MAXIMUM_AMOUNT) {
                return sprintf('%s <a href="/main.php?edit=%s&ups=%s">[+]</a>', $this->$stat_name, mt_rand(), $stat_name);
            } else {
                return $this->$stat_name;
            }
        } else {
            throw new Exception(self::ERROR_STAT_UNKNOWN);
        }
    }

    /**
     * Повышает один из выбранных статов на 1, но не выше self::STAT_MAXIMUM_AMOUNT при условии наличия свободных очков статов.
     * @param $stat_name - имя стата. Может принимать значения 'strength', 'dexterity', 'intuition', 'endurance', 'intelligence', 'wisdom'.
     * @throws \Krugozor\Database\Mysql\Exception
     */
    public function addOnePointToStat($stat_name)
    {
        $allowed = ['strength', 'dexterity', 'intuition', 'endurance', 'intelligence', 'wisdom'];
        if (in_array($stat_name, $allowed)) {
            if ($this->free_stat_points > 0 && $this->$stat_name <= self::STAT_MAXIMUM_AMOUNT) {
                $query = 'UPDATE users SET ?f = ?f + 1, free_stat_points = free_stat_points - 1 WHERE id = ?i';
                db::c()->query($query, $stat_name, $stat_name, $this->id);
            } else {
                throw new Exception(self::ERROR_STAT_IS_MAXIMUM);
            }
        } else {
            throw new Exception(self::ERROR_STAT_UNKNOWN);
        }

    }

    protected function WatcherStatus()
    {
        $query = db::c()->query('SELECT `align`,`admin` FROM `users` WHERE `id` = ?i', $this->watcher_id)->fetch_assoc();
        if ($query['admin']) {
            $this->watcherIsAdmin = 1;
        }
        if ($query['align'] == 1) {
            $this->watcherIsModerator = 1;
        }
    }

    protected function showStarSign()
    {
        /*
         * 1 aries
         * 2 taurus
         * 3 gemini
         * 4 cancer
         * 5 leo
         * 6 virgo
         * 7 libra
         * 8 scorpio
         * 9 sagittarios
         * 10 capricorn
         * 11 aquarius
         * 12 pisches
        */
        $zodiac[356] = "10";
        $zodiac[326] = "09";
        $zodiac[296] = "08";
        $zodiac[266] = "07";
        $zodiac[235] = "06";
        $zodiac[203] = "05";
        $zodiac[172] = "04";
        $zodiac[140] = "03";
        $zodiac[111] = "02";
        $zodiac[78] = "01";
        $zodiac[51] = "12";
        $zodiac[20] = "11";
        $zodiac[0] = "10";
        $dayOfYear = date("z", strtotime($this->borndate));
        $isLeapYear = date("L", strtotime($this->borndate)); //Высокосный?
        if ($isLeapYear && $dayOfYear > 59) {
            --$dayOfYear;
        }
        foreach ($zodiac as $day => $sign) {
            if ($dayOfYear > $day) {
                break;
            }
        }
        return $sign ?? null;
    }

    public function getHealth(): string
    {
        return $this->health . '/' . $this->maxHealth;
    }

    public function getMana(): string
    {
        return $this->mana . '/' . $this->maxMana;
    }
}