<?php


namespace App\Model\Crates;


use App\Model\Entities\Components\Event\Event;

class DkpRoom
{
    protected $saveRequired;

    protected $eventId;
    protected $roomName;
    protected $leaderId;
    protected $inProgress;
    protected $end;
    protected $duration;
    protected $itemName;
    protected $users;
    protected $bids;
    protected $givenTo;

    protected $grantCheckboxes;

    // temporary workaround
    protected $bidFormRedraw = false;

    public function __construct(Event $event)
    {
        $this->saveRequired = true;

        $this->eventId = $event->getId();
        $this->roomName = $event->getName();
        $this->leaderId = $event->getCreatedBy()->getId();

        $this->inProgress = false;
        $this->end = 0;
        $this->duration = 0;
        $this->itemName = '';
        $this->users = [];
        $this->grantCheckboxes = [];
        $this->clearBids();
    }

    /**
     * @return int
     */
    public function getEventId()
    {
        return $this->eventId;
    }

    /**
     * @return string
     */
    public function getRoomName()
    {
        return $this->roomName;
    }

    public function isDkpLeader($id)
    {
        return ($this->leaderId === $id);
    }

    /**
     * @return boolean
     */
    public function isInProgress()
    {
        return $this->inProgress;
    }

    /**
     * @return string
     */
    public function getItemName()
    {
        return $this->itemName;
    }

    /**
     * @return array
     */
    public function getUsers()
    {
        return $this->users;
    }

    public function addUser($id, $name)
    {
        if (!isset($this->users[$id])) {
            $this->users[$id] = [];
        }

        $this->users[$id]['name'] = $name;
        $this->saveRequired = true;
    }

    public function getUserDkp($id)
    {
        return $this->users[$id]['dkp'];
    }

    public function getUserName($id)
    {
        // used for bidders name
        // assume its initialized
        return $this->users[$id]['name'];
    }

    public function hasUser($id)
    {
        return isset($this->users[$id]);
    }

    public function hasDkp($id)
    {
        return isset($this->users[$id]['dkp']);
    }

    public function setUserDkp($id, $dkp)
    {
        // DKP are loaded after user
        // assume users[$id] exists
        $this->users[$id]['dkp'] = $dkp;

        $this->saveRequired = true;
    }

    public function startBidding(int $duration, string $name)
    {
        $this->inProgress = true;
        $this->end = time() + $duration;
        $this->duration = $duration;
        $this->itemName = $name;
        $this->clearBids();

        $this->saveRequired = true;
    }

    public function endBidding()
    {
        $this->inProgress = false;
        $this->end = false;

        $this->saveRequired = true;
    }

    public function getRemainingTime()
    {
        return max($this->end - time(), 0);
    }

    public function bid($id, $amount)
    {
        if (!isset($this->bids[$id]) || $amount > $this->bids[$id]) {
            $this->bids[$id] = $amount;

            uasort($this->bids, function ($a, $b) {
                return $b <=> $a;       // sort in reverse order
            });

            $this->saveRequired = true;
        }
    }

    public function getBid($userId)
    {
        return $this->bids[$userId];
    }

    public function getBids()
    {
        return $this->bids;
    }

    public function canBid($userId, $offset = 1)
    {
        if ($this->getRemainingTime() === 0 || !$this->isInProgress()) {
            return false;
        }

        $myDkp = $this->getUserDkp($userId);
        if ($myDkp <= 0) {
            return false;
        }

        $bids = $this->getBids();
        if (empty($bids)) {
            return true;
        }

        $highestBid = reset($bids);
        return (($highestBid + $offset) <= $myDkp);
    }

    public function repeatBidding()
    {
        $this->startBidding($this->duration, $this->getItemName());
        // save required is set in startBidding method
    }

    public function clearBids()
    {
        $this->bids = [];
        $this->givenTo = null;

        $this->saveRequired = true;
    }

    public function refreshBidForm()
    {
        // todo: remove this workaround
        if ($this->bidFormRedraw) {
            $this->bidFormRedraw = false;
            $this->saveRequired = true;
            return true;
        }

        $remainingTime = $this->getRemainingTime();

        if ($remainingTime === 0 || $remainingTime >= ($this->duration - 1)) {
            return true;
        }

        return false;
    }

    public function giveItem($userId)
    {
        $this->givenTo = $userId;

        $this->saveRequired = true;
    }

    public function givenTo($userId)
    {
        return $this->givenTo == $userId;   // given to can be numeric string
    }

    public function isSaveRequired()
    {
        return $this->saveRequired;
    }

    public function savingDone()
    {
        $this->saveRequired = false;
    }

    public function getUsersList()
    {
        $items = [];
        foreach ($this->getUsers() as $id => $user) {
            $items[$id] = $user['name'];
        }

        return $items;
    }

    /**
     * @return array
     */
    public function getGrantCheckboxes()
    {
        if (empty($this->grantCheckboxes)) {
            $this->grantCheckboxes = array_keys($this->users);
        }

        return $this->grantCheckboxes;
    }

    /**
     * @param array $grantCheckboxes
     */
    public function setGrantCheckboxes(array $grantCheckboxes)
    {
        $this->grantCheckboxes = $grantCheckboxes;

        $this->saveRequired = true;
    }

    // todo: remove this workaround
    public function bidFormRedraw()
    {
        $this->bidFormRedraw = true;

        $this->saveRequired = true;
    }

}