<?php

namespace Battles;
use Battles\Database\Db;

class Item
{
    protected int $item_id;
    protected string $name = '';
    protected int $item_type = self::ITEM_TYPE_TRASH;
    protected int $durability = 0;
    protected int $need_strength = 0;
    protected int $need_dexterity = 0;
    protected int $need_intuition = 0;
    protected int $need_endurance = 0;
    protected int $need_intelligence = 0;
    protected int $need_wisdom = 0;
    protected int $add_strength = 0;
    protected int $add_dexterity = 0;
    protected int $add_intuition = 0;
    protected int $add_endurance = 0;
    protected int $add_intelligence = 0;
    protected int $add_wisdom = 0;
    protected int $add_accuracy = 0;
    protected int $add_evasion = 0;
    protected int $add_criticals = 0;
    protected int $add_min_physical_damage = 0;
    protected int $add_max_physical_damage = 0;
    protected int $weight = 0;
    protected string $image = '';
    protected int $item_cost = 0;
    public const ITEM_TYPES_ALLOWED_IN_SLOTS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    public const ITEM_TYPE_HELMET = 1;
    public const ITEM_TYPE_ARMOR = 2;
    public const ITEM_TYPE_LEGS = 3;
    public const ITEM_TYPE_BOOTS = 4;
    public const ITEM_TYPE_GLOVES = 5;
    public const ITEM_TYPE_WEAPON = 6;
    public const ITEM_TYPE_SHIELD = 7;
    public const ITEM_TYPE_BELT = 8;
    public const ITEM_TYPE_RING = 9;
    public const ITEM_TYPE_AMULET = 10;
    public const ITEM_TYPE_CONSUMABLE = 20;
    public const ITEM_TYPE_OTHER = 50;
    public const ITEM_TYPE_TRASH = 100;
    private string $typename;

    /**
     * Item constructor.
     *
     * @param $row
     */
    public function __construct($row)
    {
        if (is_array($row)) {
            foreach ($this as $key => $value) {
                if (isset($row[$key])) {
                    $this->$key = $row[$key];
                }
            }
        } elseif (is_object($row)) {
            foreach ($this as $name => $value) {
                if (isset($row->$name)) {
                    $this->$name = $row->$name;
                }
            }
        }

        switch ($this->item_type) {
            case self::ITEM_TYPE_HELMET:
                $this->typename = 'Шлем';
                break;
            case self::ITEM_TYPE_ARMOR:
                $this->typename = 'Броня';
                break;
            case self::ITEM_TYPE_LEGS:
                $this->typename = 'Поножи';
                break;
            case self::ITEM_TYPE_BOOTS:
                $this->typename = 'Сапоги';
                break;
            case self::ITEM_TYPE_GLOVES:
                $this->typename = 'Перчатки';
                break;
            case self::ITEM_TYPE_WEAPON:
                $this->typename = 'Оружие';
                break;
            case self::ITEM_TYPE_SHIELD:
                $this->typename = 'Щит';
                break;
            case self::ITEM_TYPE_BELT:
                $this->typename = 'Пояс';
                break;
            case self::ITEM_TYPE_RING:
                $this->typename = 'Кольцо';
                break;
            case self::ITEM_TYPE_AMULET:
                $this->typename = 'Амулет';
                break;
            case self::ITEM_TYPE_CONSUMABLE:
                $this->typename = 'Расходуемый предмет';
                break;
            default:
                $this->typename = 'Хлам';
        }

        $this->item_cost = $this->calculateItemCost();
    }

    /** Рассчёт стоимости предмета в зависимости от его характеристик.
     * @return int
     */
    protected function calculateItemCost(): int
    {
        $sum_stats =
            $this->add_strength +
            $this->add_dexterity +
            $this->add_intuition +
            $this->add_endurance +
            $this->add_intelligence +
            $this->add_wisdom;
        $sum_mods =
            $this->add_accuracy +
            $this->add_evasion +
            $this->add_criticals;
        $sum_damage =
            $this->add_min_physical_damage +
            $this->add_max_physical_damage;
        // За каждые N параметров повышаем множитель на 1 чтобы цена пропрорционально росла.
        $stats_cost_modifier = 5 + floor($sum_stats / 10);
        $mods_cost_modifier = 2 + floor($sum_mods / 50);
        $damage_cost_modifier = 1 + floor($sum_damage / 100);
        $result = intval($sum_stats * $stats_cost_modifier + $sum_mods * $mods_cost_modifier + $sum_damage * $damage_cost_modifier);
        return $result < 1 ? 1 : $result;
    }

    protected function wrap(int $number): string
    {
        if ($number > 0) {
            return ": <b>" . $number . "</b>";
        } else {
            return ": <b style='color: maroon;'>" . $number . "</b>";
        }
    }

    public function getAllInfo(): string
    {
        $needsLines = [
            'сила' => $this->need_strength,
            'ловкость' => $this->need_dexterity,
            'интуиция' => $this->need_intuition,
            'выносливость' => $this->need_endurance,
            'интеллект' => $this->need_intelligence,
            'мудрость' => $this->need_wisdom,
        ];
        $addsLines = [
            'Сила' => $this->add_strength,
            'Ловкость' => $this->add_dexterity,
            'Интуиция' => $this->add_intuition,
            'Выносливость' => $this->add_endurance,
            'Интеллект' => $this->add_intelligence,
            'Мудрость' => $this->add_wisdom,
            'Точность' => $this->add_accuracy,
            'Увёртливость' => $this->add_evasion,
            'Шанс крита' => $this->add_criticals,
        ];
        $str = "<b>$this->name</b> (Масса: $this->weight)";
        $str .= '<br> Стоимость: ' . $this->item_cost;
        $str .= '<br> Долговечность: ' . $this->durability;
        $str .= "<br><em>$this->typename</em><br>";
        foreach ($needsLines as $stat => $value) {
            if ($value > 0) {
                $str .= "<br>Требуется $stat" . $this->wrap($value);
            }
        }
        foreach ($addsLines as $stat => $value) {
            if ($value) {
                $str .= "<br>$stat" . $this->wrap($value);
            }
        }
        if ($this->add_min_physical_damage && !$this->add_max_physical_damage) {
            $damage = $this->add_min_physical_damage . ' - ' . $this->add_min_physical_damage;
        } elseif (!$this->add_min_physical_damage && $this->add_max_physical_damage) {
            $damage = $this->add_max_physical_damage . ' - ' . $this->add_max_physical_damage;
        } elseif ($this->add_min_physical_damage && $this->add_max_physical_damage) {
            $damage = $this->add_min_physical_damage . ' - ' . $this->add_max_physical_damage;
        }
        if (isset($damage)) {
            $str .= '<br>Урон: ' . $damage;
        }
        return $str;
    }

    public static function getItemById($item_id): Item
    {
        return new Item(Db::getInstance()->ofetch('select * from items where id = ?', $item_id));
    }
}