<?php

namespace apexl\Io\modules\menu\services;

use apexl\ClassEngine\EngineSingleton;
use apexl\Io\includes\Hook;
use apexl\Io\modules\menu\entities\menuEntity;
use apexl\Io\modules\user\entities\userEntity;

/**
 * Class Menu
 * @package apexl\Io\modules\menu\services
 * //@todo this needs caching
 */
class Menu extends EngineSingleton
{
    public const HOOK__ADD_TO_MENU__ROUTE_NAME = 'menu.addToMenu.routeName';
    public const HOOK__ADD_TO_MENU__CONFIG = 'menu.addToMenu.config';

    protected static $menus;

    protected function __construct()
    {
        parent::__construct();
    }

    /**
     * @param $routeName
     * @param  array  $config
     * @param  string  $menu
     */
    public static function addToMenu($routeName, $config = [], $menu = 'navigation')
    {
        if (!isset(self::$menus[$menu])) {
            self::$menus[$menu] = new menuEntity();
        }

        $routeName = Hook::processHook(self::HOOK__ADD_TO_MENU__ROUTE_NAME, $routeName, $menu, $config);
        $config = Hook::processHook(self::HOOK__ADD_TO_MENU__CONFIG, $config, $menu, $routeName);

        self::$menus[$menu]->addToMenu(
            $routeName,
            $config['title'] ?? '',
            $config['icon'] ?? '',
            $config['weight'] ?? 0,
            $config['parent'] ?? false,
            $config['replacements'] ?? []
        );
    }

    /**
     * @param $routeName
     * @param  string  $menu
     * @return mixed
     */
    public static function getMenuItem($routeName, $menu = 'navigation')
    {
        if (isset(self::$menus[$menu])) {
            return self::$menus[$menu]->getMenuItem($routeName);
        }

        return null;
    }

    /**
     * @param $route
     * @param  string  $menu
     */
    public static function generateBreadcrumbs($route, $menu = 'navigation'): array
    {
        return self::$menus[$menu]->generateBreadcrumbs($route);
    }

    /**
     * This method allows us to take all registered routes and build a menu with them. We register routes as their own dynamic entity
     * @param  bool  $filterByPermission
     * @param  string  $menu
     */
    public static function getAllItemsAsMenu(userEntity $user, $menu = 'navigation', $filterByPermission = true): array
    {
        //We cache generated menu items so that the order can be controlled by admin users.
        return isset(self::$menus[$menu]) ? self::$menus[$menu]->getAllItemsAsMenu($user, $filterByPermission) : [];
    }

    /**
     * @param  string  $name
     * @return object
     */
    public static function getMenu($name = 'navigation')
    {
        return isset(self::$menus[$name]) ? self::$menus[$name] : new menuEntity();
    }

    /**
     * Get the name of the Menu containing the current route.
     * Return first menu if no match found
     * @return $menu (object)
     */
    public static function getActiveMenu()
    {
        if (isset(self::$menus) && is_array(self::$menus)) {
            foreach (self::$menus as $name => $menu) {
                $firstMenu = $menu;
                if ($menu->isCurrentMenu()) {
                    return $menu;
                }
            }
        }

        return $firstMenu ?? null;
    }
}
