<?php

namespace Snaju\Inception\Event\Types;

use Snaju\Inception\Event\Event;
use Snaju\Inception\Exception\Exception;
use Snaju\Inception\InceptionCore;
use Snaju\Inception\Route\Route;
use Snaju\Inception\Route\RouteFile;
use Snaju\Inception\Route\RouteManager;

/**
 * The OnRouteStart event is responsible for finding a matched route and
 * calling any RouteFile(s) associated with the route/path.
 *
 * @package Snaju\Inception\Event\Types
 */
class OnRouteStart extends Event
{

    private string $path;

    /**
     * OnRouteEvent constructor.
     * @param string $path
     */
    public function __construct(string $path)
    {
        $this->path = $path;
    }

    public function run(Event $event): Event
    {
        return $this;
    }

    public function onEnd(Event $event)
    {
        try {
            // Do the default routing here.
            if ($event instanceof OnRouteStart) {
                $node = &RouteManager::findRoute($event->getPath());
                if ($node instanceof Route) {

                    // Execute any route file(s) attached to the route
                    foreach ($node->getFiles() as $routeFile) {
                        if ($routeFile instanceof RouteFile) {
                            $a = call_user_func($routeFile->getFunc(), InceptionCore::getRequest(), $node);
                            if (is_array($a)) {
                                // If the route contains data (like data to be loaded in
                                // a Twig Template), set it in the TemplateManager
                                $node->data = array_merge($node->data, $a);
                            }
                        }
                    }

                    // A valid route was found
                    $node->onCall(InceptionCore::getRequest());
                } else {
                    // TODO: extend and throw other exception methods
                    throw new \Exception("No Route Found for " . $event->getPath());
                }
            } else {
                // TODO: extend and throw other exception methods
                throw new \Exception("Invalid type of event passed into OnRouteStart event.");
            }
        } catch (Exception $e) {
            (new OnNoRouteFoundEvent($e))->call();
        }

        return $event;
    }

    /**
     * @return mixed|string
     */
    public function getPath(): string
    {
        return $this->path;
    }

}