<?php /* Copyright (c) 2024 Freya Murphy */
class Router {

	private $main;
	private $load;
	private $routes;

	function load_route($route) {
		$name = $route['name'];
		$controller_cls = $route['controller'];
		$model_cls = $route['model'];

		$root = $GLOBALS['webroot'];
		$dir = $root . '/routes/' . $name;
		require($dir . '/model.php');
		require($dir . '/controller.php');

		$model_ref = new ReflectionClass($model_cls);
		$model = $model_ref->newInstance();

		$controller_ref = new ReflectionClass($controller_cls);
		$controller = $controller_ref->newInstance($model);

		return $controller;
	}

	function __construct($main, $load) {

		$routes = array(
			'home' => array(
				'slugs' => ['', 'home'],
				'model' => 'HomeModel',
				'controller' => 'HomeController',
			),
		);

		$this->routes = array();
		foreach ($routes as $name => $route) {
			foreach ($route['slugs'] as $slug) {
				$this->routes[$slug] = $route;
				$this->routes[$slug]['name'] = $name;
			}
		}

		$this->main = $main;
		$this->load = $load;
	}

	function get_info() {
		$uri = parse_url($_SERVER['REQUEST_URI']);
		$method = $_SERVER['REQUEST_METHOD'];
		$parts = explode('/', $uri['path']);

		$slug = sizeof($parts) > 1 ? $parts[1] : '';
		$path = sizeof($parts) > 2 ? $parts[2] : 'index';

		if (sizeof($parts) > 3) {
			return NULL;
		}

		return array(
			'method' => $method,
			'uri' => $uri,

			'slug' => $slug,
			'path' => $path
		);
	}

	function handle_error($code) {
		$route = array(
			'name' => 'error',
			'model' => 'ErrorModel',
			'controller' => 'ErrorController'
		);
		$this->main->info = array(
			'slug' => 'error',
			'lang' => 'en_US',
			'route' => 'error'
		);
		$controller = $this->load_route($route);
		$_GET['code'] = $code;
		http_response_code($code);
		$controller->index();
	}

	public function handle_request() {
		$request = $this->get_info();

		if ($request === NULL) {
			$this->handle_error(404);
			return;
		}

		$slug = $request['slug'];
		if (!array_key_exists($slug, $this->routes)) {
			$this->handle_error(404);
			return;
		}

		$route = $this->routes[$slug];
		$this->main->info = array(
			'lang' => 'en_US',
			'slug' => $slug,
			'route' => $route['name'],
		);

		$controller = $this->load_route($route);

		$path = $request['path'];
		$ref = NULL;

		try {
			$ref = new ReflectionMethod($controller, $path);
		} catch (Exception $_e) {}

		if ($ref === NULL || !$ref->isPublic()) {
			$this->handle_error(404);
			return;

		}

		$ref->invoke($controller);

	}

}