<?php

/**
 * プレイヤークラス
 *
 */
class Player implements BattleAble, Stringable
{
    /** @var string 名前 */
    private string $name;

    /** @var int HP */
    private int $hp;

    /** @var int 最大HP */
    private int $hpMax;

    /** @var int ATK */
    private int $atk;

    /** @var int DEF */
    private int $def;

    /** @var int CRI */
    private int $cri;

    /** @var int BLOCK */
    private int $block;

    /** @var bool $isDefence 防御状態 */
    private bool $isDefence = false;

    /** @var bool クリティカルヒットしたか */
    private bool $isCriticalHit = false;

    /** @var bool ブロック成功したか */
    private bool $isBlockSuccess = false;

    /** @var Equipment|null 装備 */
    private ?Equipment $equipment;

    /**
     * constructor
     *
     * @param int $hpMax 最大HP
     * @param int $atk ATK
     * @param int $def DEF
     * @param int $cri CRI
     * @param int $block BLOCK
     */
    public function __construct(string $name, int $hpMax, int $atk, int $def, int $cri, int $block, ?Equipment $equipment = null)
    {
        $this->equipment = $equipment;
        $this->name = $name;
        $this->hpMax = $hpMax;
        $this->hp = $this->getHpMax();
        $this->atk = $atk;
        $this->def = $def;
        $this->cri = $cri;
        $this->block = $block;
    }

    /**
     * 文字列変換
     *
     * @return string
     */
    public function __toString(): string
    {
        $equipmentName = $this->equipment?->getName() ?? 'なし';
        return "名前:{$this->getName()} HP: {$this->getHp()}/{$this->getHpMax()} ({$this->getHpRate()}%) 装備: $equipmentName";
    }

    /**
     * @inheritDoc
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @inheritDoc
     */
    public function getHp(): int
    {
        return $this->hp;
    }

    /**
     * @inheritDoc
     */
    public function subHp(int $value): void
    {
        $this->hp = max($this->hp - $value, self::HP_MIN);
    }

    /**
     * @inheritDoc
     */
    public function getHpMax(): int
    {
        return $this->hpMax + ($this->equipment?->getHpMax() ?? 0);
    }

    /**
     * @inheritDoc
     */
    public function getHpRate(): int
    {
        return $this->getHp() / $this->getHpMax() * BattleAble::PERCENTAGE;
    }

    /**
     * @inheritDoc
     */
    public function getAtk(): int
    {
        return $this->atk + ($this->equipment?->getAtk() ?? 0);
    }

    /**
     * @inheritDoc
     */
    public function getDef(): int
    {
        return $this->def + ($this->equipment?->getDef() ?? 0);
    }

    /**
     * @inheritDoc
     */
    public function getCri(): int
    {
        return $this->cri + ($this->equipment?->getCri() ?? 0);
    }

    /**
     * @inheritDoc
     */
    public function getBlock(): int
    {
        return $this->block + ($this->equipment?->getBlock() ?? 0);
    }

    /**
     * @inheritDoc
     */
    public function getTotalStatus(): int
    {
        return $this->getHpMax() + $this->getAtk() + $this->getDef() + $this->getCri() + $this->getBlock();
    }

    /**
     * @inheritDoc
     */
    public function isDead(): bool
    {
        return $this->getHp() <= 0;
    }

    /**
     * @inheritDoc
     */
    public function setDefence(bool $isDefence): void
    {
        $this->isDefence = $isDefence;
    }

    /**
     * @inheritDoc
     */
    public function isDefence(): bool
    {
        return $this->isDefence;
    }

    /**
     * @inheritDoc
     */
    public function lotteryCriticalHit(): bool
    {
        $this->setCriticalHit(RandomUtil::lottery($this->getCri()));

        return $this->isCriticalHit();
    }

    /**
     * @inheritDoc
     */
    public function setCriticalHit(bool $isCriticalHit): void
    {
        $this->isCriticalHit = $isCriticalHit;
    }

    /**
     * @inheritDoc
     */
    public function isCriticalHit(): bool
    {
        return $this->isCriticalHit;
    }

    /**
     * @inheritDoc
     */
    public function lotteryBlockSuccess(): bool
    {
        $this->setBlockSuccess(RandomUtil::lottery($this->getBlock()));

        return $this->isBlockSuccess();
    }

    /**
     * @inheritDoc
     */
    public function setBlockSuccess(bool $isBlockSuccess): void
    {
        $this->isBlockSuccess = $isBlockSuccess;
    }

    /**
     * @inheritDoc
     */
    public function isBlockSuccess(): bool
    {
        return $this->isBlockSuccess;
    }

    /**
     * @inheritDoc
     */
    public function action(BattleAble $target): Action
    {
        return new Attack($this, $target);
    }
}