<?php

namespace ComPixelCMS;

use JComponentHelper;
use Joomla\CMS\Installer\InstallerAdapter;
use Joomla\Registry\Registry;
use JTable;


class MenuItem
{
    public $id;
    public $params;
    public $link;

    protected $cast = [
        'id' => 'int',
        'params' => 'json',
        'link' => 'query'
    ];

    public function __construct(array $array)
    {
        $properties = get_object_vars($this);
        foreach($properties as $prop => $value) {
            $this->{$prop} = $this->castAttribute($prop, $array[$prop] ?? $value);
        }
    }

    protected function castAttribute(string $prop, $value)
    {
        if (isset($this->cast[$prop]) && $propType = $this->cast[$prop]) {
            switch ($propType) {
                case 'json':
                    return is_array($value) ? json_encode($value) : json_decode($value, true);
                case 'query':
                    if (!is_array($value)) {
                        parse_str( parse_url( $value, PHP_URL_QUERY), $array);
                        return $array;
                    }
                    return 'index.php?'. urldecode(http_build_query($value));
                case 'integer':
                case 'int':
                    return (int) $value;
                case 'boolean':
                case 'bool':
                    return (bool) $value;
            }
        }
        return $value;
    }

    public function setParams($params)
    {
        $this->params = array_merge($this->params, $params);
        return $this;
    }

    public function setLink($link)
    {
        $this->link = array_merge($this->link, $link);
        return $this;
    }

    public function save()
    {
        $db = \JFactory::getDbo();
        return $db->updateObject('#__menu', new MenuItem((array) $this), 'id');
    }
}

class MenuItems extends \ArrayObject {
    protected $extensionId;
    protected static $_instance = null;

    public function __construct($extensionId)
    {
        $this->extensionId = $extensionId;

        $items = array_map(function($item) {
            return new MenuItem($item);
        }, $this->load());

        if ($items) {
            parent::__construct($items);
        }
    }

    private function load(): array
    {
        $db = \JFactory::getDbo();
        $db->setQuery("SELECT id, link, params FROM #__menu WHERE component_id = $this->extensionId");

        return $db->loadAssocList();
    }

    /**
     * @param array $filterParams
     *
     * @return MenuItem[]
     *
     * @since version
     */
    public function filter(array $filterParams = [])
    {
        return array_filter($this->getArrayCopy(), function($url) use ($filterParams) {
            foreach($filterParams as $filter => $value) {
                if (is_numeric($filter)) {
                    if (substr($value, 0, 1) === '!') {
                        if (isset($url->link[substr($value, 1)])) return false;
                    } else if (!isset($url->link[$value])) return false;
                } else if ($url->link[$filter] != $value) return false;
            }
            return true;
        });
    }

    public function setLink($params, $search = [])
    {
        foreach ($this->filter($search) as $link) {
            $link->setLink($params);
        }
        return $this;
    }

    public function setParams($params, $search = [])
    {
        foreach ($this->filter($search) as $link) {
            $link->setParams($params);
        }
        return $this;
    }

    public function save($search = [])
    {
        foreach ($saved = $this->filter($search) as $link) {
            $link->save();
        }
        return $saved;
    }

    public static function getInstance($extensionId)
    {
        if (null === self::$_instance)
        {
            self::$_instance = new self($extensionId);
        }
        return self::$_instance;
    }
}

class Upgrade
{
    protected $db;
    protected $extensionId;
    protected $params;

    public function __construct(InstallerAdapter $adapter)
    {
        $this->db = \JFactory::getDbo();
        $this->extensionId = $adapter->get('currentExtensionId');
    }

    protected function getMenuItemsFiltered($filterParams): array
    {
        $urls = $this->getMenuItems();

        return $urls->filter($filterParams);
    }

    protected function getParams(): Registry
    {
        return $this->params ?? $this->params = JComponentHelper::getParams('com_pixelcms_articles');
    }

    protected function saveParams(): bool
    {
        $table = JTable::getInstance('extension');
        $table->load($this->extensionId);
        $table->bind(array('params' => $this->getParams()->toString()));

        return $table->store();
    }

    protected function getMenuItems(): MenuItems
    {
        return MenuItems::getInstance($this->extensionId);
    }

    protected function msg($msg, $type = 'message'): void
    {
        \JFactory::getApplication()->enqueueMessage($msg, $type);
    }
}
