<?php


namespace App\Components\Breadcrumb;


use Nette\Application\UI\Control;

class Breadcrumb extends Control
{
    /** @var  BreadcrumbNode */
    protected $homepage;
    /** @var  BreadcrumbNode */
    protected $firstNode;
    /** @var  BreadcrumbNode */
    protected $lastNode;
    /** @var  BreadcrumbNode */
    protected $lastInsertedNode;

    public function setHomepage(string $name, string $title, $destination, $params = array()) : BreadcrumbNode
    {
        $this->homepage = $this->createNode($name, $title, $destination, $params);
        $this->resetLastInsertedNode();
        return $this->homepage;
    }

    public function prependFirstNode(string $name, string $title, $destination, $params = array()) :  BreadcrumbNode
    {
        if ($this->firstNode === null) {
            return $this->addNode($name, $title, $destination, $params);
        }

        $node = $this->createNode($name, $title, $destination, $params);
        $this->insertBefore($node, $this->firstNode);

        return $node;
    }

    public function appendFirstNode(string $name, string $title, $destination, $params = array()) :  BreadcrumbNode
    {
        if ($this->firstNode === null) {
            return $this->addNode($name, $title, $destination, $params);
        }

        $node = $this->createNode($name, $title, $destination, $params);
        $this->insertAfter($node, $this->firstNode);

        return $node;
    }

    public function prependLastNode(string $name, string $title, $destination, $params = array()) :  BreadcrumbNode
    {
        if ($this->lastNode === null) {
            return $this->addNode($name, $title, $destination, $params);
        }

        $node = $this->createNode($name, $title, $destination, $params);
        $this->insertBefore($node, $this->lastNode);

        return $node;
    }

    public function addNode(string $name, string $title, $destination, $params = array()) : BreadcrumbNode
    {
        $node = $this->createNode($name, $title, $destination, $params);

        if ($this->firstNode === null) {
            $this->firstNode = $node;
            $this->lastNode = $node;
            $this->lastInsertedNode = $node;
        } else {
            $this->insertAfter($node, $this->lastNode);
        }

        return $node;
    }

    public function prependLastInsertedNode(string $name, string $title, $destination, $params = array()) :  BreadcrumbNode
    {
        if ($this->lastInsertedNode === null) {
            return $this->addNode($name, $title, $destination, $params);
        }

        $node = $this->createNode($name, $title, $destination, $params);
        $this->insertBefore($node, $this->lastInsertedNode);

        return $node;
    }

    public function appendLastInsertedNode(string $name, string $title, $destination, $params = array()) :  BreadcrumbNode
    {
        if ($this->lastInsertedNode === null) {
            return $this->addNode($name, $title, $destination, $params);
        }

        $node = $this->createNode($name, $title, $destination, $params);
        $this->insertAfter($node, $this->lastInsertedNode);

        return $node;
    }

    public function prependNode(BreadcrumbNode $node, string $name, string $title, $destination, $params = array()) :  BreadcrumbNode
    {
        $newNode = $this->createNode($name, $title, $destination, $params);
        $this->insertBefore($newNode, $node);

        return $newNode;
    }

    public function appendNode(BreadcrumbNode $node, string $name, string $title, $destination, $params = array()) :  BreadcrumbNode
    {
        $newNode = $this->createNode($name, $title, $destination, $params);
        $this->insertAfter($newNode, $node);

        return $newNode;
    }

    public function resetLastInsertedNode()
    {
        $this->lastInsertedNode = null;
    }

    public function render()
    {
        if ($this->homepage) {
            if ($this->firstNode === null) {
                $this->firstNode = $this->homepage;
            } else {
                $this->homepage->setNext($this->firstNode);
                $this->firstNode = $this->homepage;
            }
        }

        $this->template->setFile(__DIR__ . '/templates/breadcrumbs.latte');
        $this->template->node = $this->firstNode;
        $this->template->render();
    }

    /**
     * @param string $name
     * @param string $title
     * @param $destination
     * @param $params
     * @return BreadcrumbNode
     */
    protected function createNode(string $name, string $title, $destination, $params = array()) : BreadcrumbNode
    {
        $node = new BreadcrumbNode($this, $name);
        $node->setTitle($title);
        $node->setLink($this->presenter->link($destination, $params));
        $node->setIsActive($this->presenter->isLinkCurrent($destination, $params));

        return $node;
    }

    protected function insertBefore(BreadcrumbNode $node, BreadcrumbNode $before)
    {
        $prevNode = $before->getPrev();
        $node->setNext($before);

        if ($prevNode === null) {
            $this->firstNode = $node;
        } else {
            $node->setPrev($prevNode);
        }

        $this->lastInsertedNode = $node;
    }

    protected function insertAfter(BreadcrumbNode $node, BreadcrumbNode $after)
    {
        $nextNode = $after->getNext();
        $node->setPrev($after);

        if ($nextNode === null) {
            $this->lastNode = $node;
        } else {
            $node->setNext($nextNode);
        }

        $this->lastInsertedNode = $node;
    }
}