<?php
	require_once('base.class.php');
	require_once('router.class.php');
	require_once('response.class.php');
	require_once('events.interface.php');
	class App extends Base implements Events {
		private static $apps = array();
		private $routers;
		public function __construct($name){
			$this->name = $name;
			$this->routers = array();
			static::$apps[] = $this;
		}
		public function __destruct(){
			$this->routers = array();
			$index = array_search(static::$apps, $this);
			if($index !== false){
				array_splice(static::$apps, $index, 1);
			}
			if(is_callable('parent::__destruct')){
				parent::__destruct();
			}
		}
		public static function shutdown(){
			$verb = $_SERVER['REQUEST_METHOD'];
			$url = parse_url($_SERVER['REDIRECT_URL']);
			$data = file_get_contents( 'php://input','r');
			foreach(static::$apps as $k => $app){
				if($app instanceof App){
					$app->handle($verb, $url, $data);
				}
			}
			if(is_callable('parent::__destruct')){
				parent::__destruct();
			}
		}
		public static function shutdown_error($error){
			foreach(static::$apps as $k => $app){
				$app->error($error);
			}
		}
		public function handle($verb, $url, $data){
			$res = new Response();
			$self = $this;
			$onerror = function($res, $error){
				$self->error($error);
			};
			foreach($this->routers as $type => $routers){
				foreach($routers as $router){
					switch($type){
						case 'prefix':
							$router->handle($url["path"], $res, null, $onerror);
						break;
						case 'domain':
							$router->handle($url["host"], $res, null, $onerror);
						break;
					}
				}
			}
			$res->url = $url;
			return $res;
		}
		public function error($error){

		}
		public function get_router($type, $path){
			$ret = false;
			if(isset($this->routers[$type])){
				foreach($this->routers[$type] as $k => $router){
					if($router->base == $path){
						$ret = $router;
					}
				}
			}
			return $ret;
		}
		public function create_router($type, $path){
			$router = new Router($path);
			if(!isset($this->routers[$type])){
				$this->routers[$type] = array();
			}
			$this->routers[$type][] = $router;
			return $router;
		}
		public function route($type, $path, Callable $fn){
			$router = $this->get_router($type, $prefix);
			if($router == false){
				$router = $this->create_router($type, $prefix);
			}
			$fn($router);
		}
		public function prefix($prefix, Callable $fn){
			$this->route('prefix', $prefix, function($router){
				$router->base($prefix);
				$fn($router);
			});
		}
		public function domain($prefix, Callable $fn){
			$this->route('domain', $prefix, function($router){
				$router->base($prefix);
				$fn($router);
			});
		}
	}
	error_reporting(E_ALL);
	ini_set('display_errors', 'On');
	register_shutdown_function(function(){
		App::shutdown();
	});
	set_error_handler(function($errno, $errstr, $errfile, $errline){
		App::shutdown_error(array(
			'number'=> $errno,
			'msg'=> $errstr,
			'file'=> $errfile,
			'line'=> $errline,
			'backtrace'=> debug_backtrace(),
			'included'=> get_included_files()
		));
	},E_ALL);
	register_shutdown_function(function(){
		$error = error_get_last();
		if($error['type'] == 1){
			App::shutdown_error(array(
				'number'=> $error['type'],
				'msg'=> $error['message'],
				'file'=> $error['file'],
				'line'=> $error['line'],
				'backtrace'=> array(),
				'included'=> get_included_files()
			));
		}
	});
?>