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

	// the loader
	private $load;

	// the main model
	private $main;

	/**
	 * Creates a router
	 * @param Loader $load - the main laoder object
	 */
	function __construct($load) {
		$this->load = $load;
		$this->main = $this->load->model('main');
	}

	/**
     * @param string $path - the current request path
	 * Gets the current route
	 * @return array<string,mixed>
	 */
	private function get_req_route($path): array {
		// trim the path
		$path = trim($path);
		// remove first '/'
		$path = substr($path, 1);
		// get path parts
		$parts = explode('/', $path);

		$len = count($parts);

		// get route info
		$route = array();
		// e.g. /
		if ($path === '') {
			$route = array(
				'route' => '',
				'slug' => 'index',
			);
		// e.g. /home /login
		} else if ($len === 1) {
			$route = array(
				'route' => $parts[0],
				'slug' => 'index',
			);
		// e.g. /home/posts
		} else {
			$route = array (
				'route' => implode('/', array_slice($parts, 0, -1)),
				'slug' => end($parts)
			);
		};

		$route['app'] = $route['route'];
		$routes = $GLOBALS['routes'];
		if (array_key_exists($route['route'], $routes)) {
			$route['route'] = $routes[$route['route']];
		}

		return $route;
	}

	/**
	 * Gets the curret request info
	 * @return array<string,mixed>
 	 */
	private function get_req(): array {
		$method = $_SERVER['REQUEST_METHOD'];

		$uri = parse_url($_SERVER['REQUEST_URI']);
		$path = $uri['path'];

		return array_merge(
			array(
				'uri' => $uri,
				'method' => $method,
				'lang' => $this->get_lang(),
			),
			$this->get_req_route($path),
		);
	}

	/**
	 * Gets the current language
	 * @return string
	 */
	private function get_lang(): string {
		return 'en_US';
	}

	/**
	 * Handles a router error code
	 * @param int $code - the http error code
	 * @param bool $recursed
	 */
	private function handle_error($code, $recursed): void {
		if ($recursed) {
			die($code . ' (recursed)');
		}

		$this->main->info['slug'] = 'index';
		$this->main->info['app'] = 'error';
		$this->main->info['route'] = 'apps/error';
		$req = $this->main->info;
		$_GET['code'] = $code;

		$this->handle_req($req, TRUE);
	}

	/**
	 * @param array $req
	 * @param bool $recursed
	 */
	private function handle_req($req, $recursed = FALSE): void {
		$controller = $this->load->controller($req['route']);

		if ($controller === NULL) {
			$this->handle_error(404, $recursed);
			return;
		}

		$ref = NULL;
		try {
			$ref = new ReflectionMethod($controller, $req['slug']);
		} catch (Exception $_e) {}

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

		}

		$ref->invoke($controller);
	}

	/**
     * Handels the incomming reuqest
     */
    public function handle_request(): void {
		$req = $this->get_req();
		$this->main->info = $req;
		$this->handle_req($req);
	}

}