<?php

/**
 * Questo file è parte di Pongho.
 *
 * @author    Daniele De Nobili
 * @copyright Web Agency Meta Line S.r.l.
 * @package   Application\Admin
 */

namespace Application\Admin\Panels;

use Application\Admin\Utilities\PonghoUrl;

class PanelsManager implements \IteratorAggregate
{
    /**
     * @var PanelInterface[]
     */
    protected $panels = [];

    /**
     * @var string
     */
    protected $active;

    /**
     * @var bool
     */
    protected $external_link = false;

    /**
     * @var string
     */
    protected $path;

    /**
     * @var PonghoUrl
     */
    protected $pongho_url;

    /**
     * @param bool      $external_link
     * @param string      $path
     * @param PonghoUrl $pongho_url
     */
    public function __construct($external_link = false, $path = '', ?PonghoUrl $pongho_url = null)
    {
        if ($external_link && ($path === '' || !$pongho_url instanceof PonghoUrl)) {
            throw new \InvalidArgumentException('You must specify a path and a PonghoUrl instance if you want external links.');
        }

        $this->external_link = $external_link;
        $this->path = rtrim($path, '/') . '/';
        $this->pongho_url = $pongho_url;
    }

    /**
     * Aggiunge un pannello.
     *
     * @return $this
     */
    public function add(PanelInterface $panel)
    {
        $key = $this->validatePanelKey($panel);

        $this->panels[$key] = $panel;

        return $this;
    }

    /**
     * Aggiunge un pannello all'inizio della collezione.
     *
     * @return $this
     */
    public function addFirst(PanelInterface $panel)
    {
        $key = $this->validatePanelKey($panel);

        $panels = [$key => $panel];

        foreach ($this->panels as $key => $panel) {
            $panels[$key] = $panel;
        }

        $this->panels = $panels;

        return $this;
    }

    /**
     * Indica se esiste un pannello con la chiave passata.
     *
     * @param string $key
     * @return bool
     */
    public function has($key)
    {
        return isset($this->panels[$key]);
    }

    /**
     * Restituisce un pannello.
     *
     * @param string $key
     * @return PanelInterface
     */
    public function get($key)
    {
        if (!isset($this->panels[$key])) {
            throw new \InvalidArgumentException(sprintf('Panel "%s" not exists.', $key));
        }

        return $this->panels[$key];
    }

    /**
     * @return array
     */
    public function keys()
    {
        return array_keys($this->panels);
    }

    /**
     * Rimuove un pannello.
     *
     * @param string $key
     * @return $this
     */
    public function del($key)
    {
        unset($this->panels[$key]);

        return $this;
    }

    /**
     * Imposta il pannello attivo.
     *
     * @param string $key
     * @return $this
     */
    public function setActive($key)
    {
        if (!isset($this->panels[$key])) {
            throw new \InvalidArgumentException(sprintf('Panel "%s" not exists.', $key));
        }

        $this->active = $key;

        return $this;
    }

    /**
     * @return string
     */
    public function render()
    {
        $active = $this->getActivePanelKey();

        $tabs = '';
        $panels = '';
        foreach ($this->panels as $key => $panel) {
            $is_active = $active === $key;

            $tabs .= $is_active ? '<li class="active">' : '<li>';
            $tabs .= '<a href="' . $this->getPanelUrl($key) . '">' . $panel->getTitle() . '</a></li>';

            if ($this->external_link && !$is_active) {
                continue;
            }

            $panels .= '<div class="panel" id="panel-' . $key . '">' . $panel->getContent() . '</div>';
        }

        $ul_class = 'tabs';

        if ($this->external_link) {
            $ul_class .= ' nojs';
        }

        return '<ul class="' . $ul_class . '">' . $tabs . '</ul><div class="panels">' . $panels . '</div>';
    }

    /**
     * {@inheritdoc}
     */
    public function getIterator(): \Traversable
    {
        return new \ArrayIterator($this->panels);
    }

    /**
     * @return string
     */
    protected function validatePanelKey(PanelInterface $panel)
    {
        $key = $panel->getKey();

        if (!is_string($key)) {
            throw new \LogicException(sprintf('The key of the "%s" panel is not of type string.', $panel->getTitle()));
        }

        return $key;
    }

    /**
     * @return string
     */
    protected function getActivePanelKey()
    {
        if ($this->active === null) {
            $panels = array_keys($this->panels);

            $this->active = reset($panels);
        }

        return $this->active;
    }

    /**
     * @param string $panel_key
     * @return string
     */
    protected function getPanelUrl($panel_key)
    {
        if ($this->external_link) {
            if ($this->getActivePanelKey() === $panel_key) {
                return $this->pongho_url->url($this->path);
            }

            return $this->pongho_url->url($this->path . $panel_key . '/');
        }

        return '#panel-' . $panel_key;
    }
}
