<?php

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

namespace Dotclear\Module;

use Dotclear\App;
use Dotclear\Core\Backend\Icon;
use Dotclear\Core\Backend\Menu;
use Dotclear\Core\Backend\Menus;
use Dotclear\Helper\Html\Form\Hidden;

/**
 * @brief   Plugin My module class.
 *
 * A plugin My class must extend this class.
 *
 * @since   2.27
 */
abstract class MyPlugin extends MyModule
{
    protected static function define(): ModuleDefine
    {
        return self::getDefineFromNamespace(App::plugins());
    }

    /**
     * Register backend sidebar menu item.
     *
     * @param   string                  $menu   The menu (from Utility constant)
     * @param   array<string,string>    $params The URL params
     * @param   string                  $scheme The URL end scheme
     * @param   string                  $id     The id (if not provided a standard one will be set), will be prefixed by 'plugin-'
     */
    public static function addBackendMenuItem(string $menu = Menus::MENU_PLUGINS, array $params = [], string $scheme = '(&.*)?$', ?string $id = null): void
    {
        if (!App::task()->checkContext('BACKEND') || !(App::backend()->menus()[$menu] instanceof Menu)) {
            return;
        }

        $request_uri = isset($_SERVER['REQUEST_URI']) && is_string($request_uri = $_SERVER['REQUEST_URI']) ? $request_uri : '';

        App::backend()->menus()[$menu]->addItem(
            self::name(),
            static::manageUrl($params, '&'),
            static::icon(),
            (bool) preg_match('/' . preg_quote(static::manageUrl([], '&'), '/') . $scheme . '/', $request_uri),
            self::checkContext(static::MENU),
            'plugin-' . ($id ?? self::id())
        );
    }

    /**
     * Get modules icon URLs.
     *
     * Will use SVG format is exist, else PNG
     *
     * @param   string    $suffix   Optionnal suffix (will be prefixed by - if any)
     *
     * @return  string[]   The module icons URLs
     */
    public static function icons(string $suffix = ''): array
    {
        $check = fn (string $base, string $name): false|string => (file_exists($base . DIRECTORY_SEPARATOR . $name . '.svg') ?
            static::fileURL($name . '.svg') :
            (file_exists($base . DIRECTORY_SEPARATOR . $name . '.png') ?
                static::fileURL($name . '.png') :
                false));

        $icons = [];
        if (App::task()->checkContext('BACKEND')) {
            // Light mode version
            if ($icon = $check(self::path(), 'icon' . ($suffix !== '' ? '-' . $suffix : ''))) {
                $icons[] = $icon;
            }

            // Dark mode version
            if ($icon = $check(self::path(), 'icon-dark' . ($suffix !== '' ? '-' . $suffix : ''))) {
                $icons[] = $icon;
            }
        }

        if ($icons === [] && $suffix) {
            // Suffixed icons not found, try without
            return static::icons();
        }

        return $icons;
    }

    /**
     * Get modules icon (backend component)
     *
     * @param   string    $suffix   Optionnal suffix filename (will be prefixed by - if any)
     *
     * @return Icon     The module icon
     *
     * @since 2.39
     */
    public static function icon(string $suffix = ''): Icon
    {
        $icons = static::icons($suffix);

        return new Icon($icons[0] ?? '', $icons[1] ?? '');
    }

    /**
     * Get module backend url.
     *
     * @param   array<string,string|int>    $params     The URL parameters
     * @param   string                      $separator  The query string separator
     * @param   bool                        $parametric Set to true if url will be used as (s)printf() format
     */
    public static function manageUrl(array $params = [], string $separator = '&amp;', bool $parametric = false): string
    {
        return App::task()->checkContext('BACKEND') ? App::backend()->url()->get('admin.plugin.' . self::id(), $params, $separator, $parametric) : '';
    }

    /**
     * Get form hidden fields.
     *
     * @param   array<string,string|int>    $params     The additionnal parameters
     *
     * @return  Hidden[]
     */
    public static function hiddenFields(array $params = []): array
    {
        $fields = [];
        if (App::task()->checkContext('BACKEND')) {
            $params = [
                ...App::backend()->url()->getParams('admin.plugin.' . self::id()),
                ...$params,
            ];
            foreach ($params as $key => $value) {
                $fields[] = new Hidden([$key], is_scalar($value) ? (string) $value : null);
            }

            $fields[] = App::nonce()->formNonce();
        }

        return $fields;
    }

    /**
     * Get rendered form hidden fields.
     *
     * @param   array<string,string|int>    $params     The additionnal parameters
     */
    public static function parsedHiddenFields(array $params = []): string
    {
        $res = '';
        foreach (self::hiddenFields($params) as $field) {
            $res .= $field->render();
        }

        return $res;
    }

    /**
     * Get module backend redirection.
     *
     * @param   array<string,string|int>    $params     The URL parameters
     * @param   string                      $suffix     The URL suffix (#)
     */
    public static function redirect(array $params = [], string $suffix = ''): void
    {
        if (App::task()->checkContext('BACKEND')) {
            App::backend()->url()->redirect('admin.plugin.' . self::id(), $params, $suffix);
        }
    }
}
