<?php

namespace SHServ;

use \Fury\Modules\Router\Router;
use \Fury\Modules\ThinBuilder\ThinBuilder;
use \Fury\Modules\ErrorHandler\ErrorHandler;
use \SHServ\Factory\Factory;
use \SHServ\DevTools;

class App extends \Fury\Kernel\BaseApp{
	public $routes;
	public $router;
	public $events_handlers;
	public $error_handlers;
	public $thin_builder;
	public $console_flag;

	// CUSTOM
	public $utils;
	public $factory;
	public $devtools;

	public $control_scripts_instances = [];
	public $scripts_registry;

	public function __construct() {
		parent::__construct();

		global $argv;
		$this -> console_flag = isset($argv) ? true : false;
		$this -> app_init();

	}

	public function app_init(): void {
		if(!$this -> console_flag) {
			$this -> error_handlers = new ErrorHandler();
		}

		\Fury\Modules\Template\Template::set_driver(new \Fury\Drivers\TemplateDriver());

		$this -> router_json_to_post_emulate();

		$this -> devtools = new DevTools();
		$this -> router = new Router();
		$this -> routes = new Routes($this -> router);
		$this -> thin_builder = new ThinBuilder(FCONF['db'], new \Fury\Drivers\ThinBuilderDriver(bootstrap()));
		$this -> control_scripts_init();
		$this -> events_handlers = new EventsHandlers();
		$this -> events_handlers -> handlers();

		$this -> request_logger = new \SHServ\Middleware\RequestLogger();
		$this -> sql_logger     = new \SHServ\Middleware\SqlQueryLogger();

		// CUSTOM
		$this -> utils = new Utils();
		$this -> factory = new Factory();
	}

	public function root_folder(): String {
		return dirname(__DIR__, 2);
	}

	protected function router_json_to_post_emulate(): void {
		$content_type = $_SERVER['CONTENT_TYPE'] ?? '';

		if (stripos($content_type, 'application/json') === false) {
	    return;
		}

		$raw_body = file_get_contents('php://input');
		$json_data = json_decode($raw_body, true);

		if (json_last_error() !== JSON_ERROR_NONE) {
	    return;
		}

		foreach($json_data as $param_name => $param_val) {
			$_POST[$param_name] = $param_val;
		}
	}

	public function control_scripts_init(): void {
		$this -> scripts_registry = new \SHServ\Middleware\ScriptsRegistry();
		$this -> scripts_registry -> flush();
		$this -> control_scripts_instances = [];

		// Ensure ModesRegistry is loaded for lazy sync in ModesContext
		$modesRegistryPath = __DIR__ . "/../../automation/ModesRegistry.php";
		if(file_exists($modesRegistryPath)) {
			require_once $modesRegistryPath;
		}

		$scopeDir = __DIR__ . "/../../automation/Scopes";
		$files = glob($scopeDir . "/*.php");

		foreach($files as $file) {
			$beforeClasses = get_declared_classes();
			require_once $file;
			$afterClasses = get_declared_classes();
			$newClasses = array_diff($afterClasses, $beforeClasses);

			foreach($newClasses as $className) {
				if(!class_exists($className)) {
					continue;
				}
				$interfaces = class_implements($className);
				if(!isset($interfaces[\SHServ\Implements\ControlScriptsInterface::class])) {
					continue;
				}
				$ref = new \ReflectionClass($className);
				if($ref -> getNamespaceName() !== "ControlScripts\\Scopes") {
					continue;
				}

				$script_name = $ref -> getShortName();
				$script = new $className();
				$this -> control_scripts_instances[$script_name] = $script;
			}
		}
	}
}

if (!defined('PHPUNIT_TEST') || !PHPUNIT_TEST) {
	new App();
}
