<?php

namespace Signteer\Web\Common\Ui\Renderer;

use Plainwork\Http\Request;
use Plainwork\Http\Router;
use Plainwork\Ui\Component\Main;
use Plainwork\Ui\Component\Menu;
use Plainwork\Ui\Component\Link;
use Plainwork\Ui\Renderer\MenuRenderer;
use Plainwork\Ui\Html;
// use ShiftExec\Core\Web\Acl;
// use ShiftExec\Core\Model\User;

final class MainRenderer
{
    public $router = Router::class;
    public $menuRenderer = MenuRenderer::class;
    // public $acl = Acl::class;
    // public $user = User::class;

    public function __invoke(Main $el, Request $request, callable $next)
    {
        $ret = $this->render($el, $request);
        $ret = new Main($ret);

        return $next($ret, $request);
    }

    private function render(Main $el, Request $request)
    {
        $path = $request->getRequestedPath();

    // all path stack starting from absolute root
        $pathArray = strlen($path) ? explode('/', $path) : [];
        $pathStack = [];
        for ($i = 0; $i <= count($pathArray); $i++) {
            $path_ = join('/', array_slice($pathArray, 0, $i));
            $pathStack[] = $path_;
        }

        $html = new Html();

        $ret = [];

    // someone willing to decorate?
        // list($route,) = $this->router->parsePath($path);
        // $layoutHandlerChain = $this->router->find($route, 'layout');
        // foreach ($layoutHandlerChain as $layoutHandler) {
            // $el = $this->app->call($layoutHandler, $el, $request);
        // }

        $mainMenuView = $this->renderMainMenu($el->mainMenu, $request);

    // breadcrumbs
        $breadcrumbs = [];
        foreach ($pathStack as $path_) {
            if (!strlen($path_)) {
                continue;
            }
            if ($path_ === $path) {
                break;
            }

            $label = $this->getBreadcrumbTitle($path_);
            if (null === $label) {
                continue;
            }

            $link = $html->link($path_, [], $label);
            $breadcrumbs[] = $link;
        }

        if ($el->titleMenu->hasItems()) {
            $title = $html->inlineList($el->title, $el->titleMenu);
        } else {
            $title = $el->title;
        }

        if ($breadcrumbs) {
            $breadcrumbsView = $html->breadcrumbs($breadcrumbs);
            $mainMenuView = $html->blockList($mainMenuView, $breadcrumbsView);
        }

        // $retImpersonatedUser = $this->renderImpersonatedUser($request);
        // if ($retImpersonatedUser) {
            // $ret[] = $retImpersonatedUser;
        // }

        $ret[] = $mainMenuView;
        $ret[] = $title;
        $ret[] = $el->menu;
        $ret[] = $el->content;

        if ($el->afterContentMenu->hasItems()) {
            $ret[] = $el->afterContentMenu;
        }

        if ($el->bottomMenu->hasItems()) {
            $ret[] = $el->bottomMenu;
        }

        $ret = $html->blockList($ret)->largeSpacing();

        return $ret;
    }

    private function renderMainMenu(Menu $el, Request $request)
    {
        $html = new Html();

        $ret = '';

        $items = $el->getItems();
        $items = array_filter($items, fn($e) => $this->menuRenderer->isItemAllowed($e, $request));
        if (!$items) {
            return $ret;
        }

        $currentPath = $request->getPath();
        $currentPathArray = strlen($currentPath) ? explode('/', $currentPath) : [];

        $ret = $html->tabMenu();

        foreach ($items as $i => $item) {
            $isOn = false;
            if ($item instanceof Link) {
                // $item->setMenu(true);

                $path_ = $request->resolvePath($item->getPath());
                $pathArray_ = strlen($path_) ? explode('/', $path_) : [];

                $len = min(count($pathArray_), count($currentPathArray));
                $isOn = true;
                for ($i_ = 0; $i_ < $len; $i_++) {
                    if ($pathArray_[$i_] !== $currentPathArray[$i_]) {
                        $isOn = false;
                        break;
                    }
                }
            }

            $ret->add($i, $item);
            if ($isOn) {
                $ret->setCurrent($i);
            }
        }

        return $ret;
    }

    private function getBreadcrumbTitle(string $path)
    {
        list($route,) = $this->router->parsePath($path);
        if (null === $route) {
            return;
        }

        $ret = $this->router->find($route, 'breadcrumb');
        $ret = $ret ? current($ret) : null;

        return $ret;
    }

    private function renderImpersonatedUser(Request $request)
    {
        $impersonatedUserId = $this->acl->getImpersonatedUserId($request);
        if (null === $impersonatedUserId) {
            return;
        }

        $impersonatedUser = $this->user->get($impersonatedUserId);
        if (!$impersonatedUser) {
            return;
        }

        $html = new Html();

        $ret = $html->inlineList();

        $v = $impersonatedUser->title;
        $v = $html->el('b', $v);
        $v = $html->link('admin/user/' . $impersonatedUser->id, ['u*' => null], $v);
        $ret->add('__Viewing as:__', $v);

        $menu = $html->menu();
        $menu->add($html->link('.', ['u*' => null], $html->icon()->delete(), '__Stop impersonating__'));
        $ret->add($menu);

        return $ret;
    }
}
