<?php 
namespace App\Core\Routing;
use \App\Core\Http\Request ;
use \App\Core\Routing\Route;
class Router
{
    private $request ;
    private $routes ;
    private $currentRoute ;
    const BASE_CONTROller = "\App\Controllers\\" ;

    public function __construct()
    {
        $this->request = new Request() ;
        $Routes = new Route();
        $this->routes = $Routes::routes();
        $this->currentRoute = $this->FindRoutes($this->request) ?? null;
        $this->RunRoutesMiddleware();
    }
    private function RunRoutesMiddleware()
    {
        $middlewares = $this->currentRoute["Middleware"];
        foreach ($middlewares as $middleware)
        {
            $middleware_obj = new $middleware ;
            $middleware_obj->handle();
        }
    }
    public function FindRoutes( Request $request)
    {
        foreach ($this->routes as $route)
        {
            if(in_array($request::method() , $route['methods'])  and  $request::uri() == $route["uri"] )
            {
                return $route ;
            }
        }
        return null ;
    }
    public function dispatch404()
    {
        header("HTTP/1.0 404 Not Found");
        view("error/404");
        die();
    }
    public function run()
    {
        // 404
        if(is_null($this->currentRoute))
        {
            $this->dispatch404();
        }
        // null
        if (is_null($this->currentRoute["action"]) or empty($this->currentRoute['action']))
        {
            return;
        }
        // callable
        if (is_callable($this->currentRoute["action"]))
        {
            call_user_func($this->currentRoute["action"]);
        }
        // string
        if(is_string($this->currentRoute["action"]))
        {
            $this->currentRoute["action"] = explode("@",$this->currentRoute["action"]);
        }
        //array
        if(is_array($this->currentRoute["action"]))
        {
            $action = $this->currentRoute["action"];
            $class_name = self::BASE_CONTROller . $action[0];
            $method = $action[1];
            if(!class_exists($class_name))
            {
                throw new \Exception("class $class_name not exists !");
            }
            $controller = new $class_name() ;
            if (!method_exists($controller,$method))
            {
                throw new \Exception("method $method not found");
            }
            $controller->{$method}();
        }
    }
}