<?php

namespace Snaju\Inception\Route\Loaders\Twig;

use Snaju\Inception\Exception\Exception;
use Snaju\Inception\Http\Request\WebRequest;
use Snaju\Inception\InceptionCore;
use Snaju\Inception\Route\Route;
use Snaju\Inception\Util\Loaders\Queue;
use Snaju\Inception\Util\Loaders\Stack;
use Snaju\Inception\Util\Util;
use Twig\Compiler;
use Twig\Environment;
use Twig\Extension\CoreExtension;
use Twig\Node\IncludeNode;
use Twig\Node\ModuleNode;
use Twig\Node\Node;
use Twig\NodeVisitor\OptimizerNodeVisitor;
use Twig\Source;
use Twig\Token;

class TwigRoute extends Route
{

    private string $twigId;

    private Queue $allExecuted;

    private array $controllers = [];

    private Source $source;

    private Environment $env;

    /**
     * TwigRoute constructor.
     * @param $pathTo
     * @param $twigId
     */
    public function __construct($pathTo, $twigId)
    {
        $this->twigId = $twigId;
        $this->allExecuted = new Queue();

        parent::__construct($pathTo);
    }

    public function preLoadTemplate($twigId)
    {
        if (isset(TemplateManager::$templates[$twigId])) {
            $template = TemplateManager::$templates[$twigId];
            if ($template instanceof Template) {
                $this->source = new Source(file_get_contents($template->getLocation()), $template->getId(), '');
                $stream = TemplateManager::$env->tokenize($this->source);
                $parse = TemplateManager::$env->parse($stream);

                $this->searchForControllers($parse);
            }
        }
    }

    public function fromIdToControllers($twigId, bool $pushFirst = false): void
    {
        if (isset(TemplateManager::$templates[$twigId])) {
            $t = TemplateManager::$templates[$twigId];
            if ($t instanceof Template) {
                $var = $t->getLocation();
                $varDir = dirname($var);
                $dirs = str_replace(InceptionCore::getBase(), "", $varDir);
                $dParts = Util::cleanArray(explode("/", $dirs));
                $i = count($dParts);
                foreach ($dParts as $ii => $part) {
                    $allname = InceptionCore::getBase() . "/" . implode("/", $dParts) . "/" . "_all.php";
                    if (file_exists($allname)) {
                        if ($pushFirst) {
                            array_unshift($this->controllers, $allname);
                        } else {
                            $this->controllers[] = $allname;
                        }
                    }
                    unset($dParts[--$i]);
                }

                $phpLoc = str_replace(".twig", ".php", $var);

                if (file_exists($phpLoc)) {
                    if ($pushFirst) {
                        array_unshift($this->controllers, $phpLoc);
                    } else {
                        $this->controllers[] = $phpLoc;
                    }
                }
            }
        }
    }

    public function searchForControllers(Node $node)
    {
        if ($node->hasNode("parent")) {
            $this->preLoadTemplate($node->getNode("parent")->getAttribute("value"));
            $this->fromIdToControllers($node->getNode("parent")->getAttribute("value"),true);
        }

        if ($node instanceof IncludeNode) {
            if ($node->hasNode("expr")) {

                $str = TemplateManager::$env->compile($node->getNode("expr"));
                $context = (array)TemplateManager::$context;
                ob_start();
                eval("echo " . $str . ";");
                $realVal = ob_get_clean();

                $this->preLoadTemplate($realVal);
                $this->fromIdToControllers($realVal);
            }
        }

        foreach ($node->getIterator() as $n) {
            if ($n instanceof Node) {
                $this->searchForControllers($n);
            }
        }

    }

    public function runControllers()
    {
        foreach ($this->controllers as $var) {
            $a1 = require $var;
            if (is_array($a1)) {
                TemplateManager::merge($a1);
            }
        }
    }

    public function onCall(WebRequest $request)
    {
        $this->env = TemplateManager::$env;
        $this->fromIdToControllers($this->twigId);
        $this->preLoadTemplate($this->twigId);
        $this->runControllers();

        // Final Render Pass
        $render = TemplateManager::render($this->twigId);

        echo $render;
//        exit(200);
    }
}