<?php

/**
 * @package     Dotclear
 * @subpackage  Upgrade
 *
 * @copyright   Olivier Meunier & Association Dotclear
 * @copyright   AGPL-3.0
 */
declare(strict_types=1);

namespace Dotclear\Core\Upgrade;

use ArrayObject;
use Dotclear\App;
use Dotclear\Core\Backend\Menu as BackendMenu;
use Dotclear\Core\Backend\Icon as BackendIcon;

/**
 * @brief   Utility class for Upgrade menu stack.
 *
 * @extends ArrayObject<string, BackendMenu>
 *
 * @since   2.29
 */
class Menus extends ArrayObject
{
    /**
     * Menu sections.
     *
     * @var     string MENU_SYSTEM
     */
    public const MENU_SYSTEM = 'System';

    /**
     * Prepend menu group.
     *
     * @param   string          $section    The menu section
     * @param   BackendMenu     $menu       The menu instance
     */
    public function prependSection(string $section, BackendMenu $menu): void
    {
        $stack = $this->getArrayCopy();
        $stack = [$section => $menu] + $stack;
        $this->exchangeArray($stack);
    }

    /**
     * Adds a menu item.
     *
     * @param      string                       $section   The section
     * @param      string                       $desc      The item description
     * @param      string                       $adminurl  The URL scheme
     * @param      string|string[]|BackendIcon  $icon      The icon(s)
     * @param      bool                         $perm      The permission(s)
     * @param      bool                         $pinned    Is pinned at begining
     * @param      bool                         $strict    Strict URL scheme or allow query string parameters
     * @param      string                       $id        The menu item id
     */
    public function addItem(string $section, string $desc, string $adminurl, string|array|BackendIcon $icon, bool $perm, bool $pinned = false, bool $strict = false, ?string $id = null): void
    {
        if (!App::task()->checkContext('UPGRADE') || !$this->offsetExists($section)) {
            return;
        }

        // Use class from Backend
        App::task()->addContext('BACKEND');

        $url         = App::upgrade()->url()->get($adminurl);
        $pattern     = '@' . preg_quote($url) . ($strict ? '' : '(&.*)?') . '$@';
        $request_uri = isset($_SERVER['REQUEST_URI']) && is_string($request_uri = $_SERVER['REQUEST_URI']) ? $request_uri : '';

        $this->offsetGet($section)?->addItem(
            $desc,
            $url,
            $icon,
            (bool) preg_match($pattern, $request_uri),
            $perm,
            $id,
            null,
            $pinned
        );
    }

    /**
     * Set default menu titles and items.
     */
    public function setDefaultItems(): void
    {
        // nullsafe and context
        if (!App::task()->checkContext('UPGRADE')) {
            return;
        }

        // add menu sections
        $this->offsetSet(self::MENU_SYSTEM, new BackendMenu('system-menu', __('System')));

        foreach (App::upgrade()->getIcons() as $icon) {
            $this->addItem(
                self::MENU_SYSTEM,
                $icon->name,
                $icon->url,
                new BackendIcon($icon->icon, $icon->dark),
                $icon->perm,
                true,
                false,
                $icon->id
            );
        }
    }
}
