<?php

/**
 * Ядро сайта. Центральная точка входа для выполнения запроса и доступа к
 * основным объектам, т.к. renderer, currentUser, siteConfig.
 *
 * 
 *
 *
*/
class carabiSite
{

	protected static $requestHandler;
	protected static $renderer;

	/**
	 * Поисковики обработичка запроса. Соответствуют именам классов. Классы
	 * должны реализовывать интерфейс iRequestHandlerFinder
	*/
	protected static $requestHandlerFinders = array(ServiceCallHandler, SimplePagehandlerFinder);


	/**
	 * Выполняет подготовку ядра.
	 *
	 * @todo Функцию в protected, вызывать из метода execute
	 *
	*/
	static public function prepare()
	{
		self::catchExceptions();
		self::includeFiles();
		spl_autoload_register(array(__CLASS__, 'autoloader'));
		spl_autoload_register(array(__CLASS__, 'autoloader_namespace'));
		global $conn;
		
		$conn = ora_connect();
		mb_internal_encoding("UTF-8");
	}



	/**
	 * Определяет цель запроса и выполнят его обработчик.
	 *
	 * @todo придумать нормальное именование метода
	 * @todo вызывать настройку ядра
	*/
	static public function execute()
	{
		try {
			utls::logStr("Carabi started: " . date('Y.m.d H:i:s'));
			utls::logStr("SERVER: " . print_r($_SERVER, true));
			utls::logStr("REQUEST: " . print_r($_REQUEST, true));
			utls::logStr("COOKIE: " . print_r($_COOKIE, true));
			ob_start();
			self::executeNormalFlow();
			ob_end_flush();
		} catch (ExceptionLogin $e) {
			$_SESSION["REDIRECT_TO_AFTER_LOGIN"] = $e->wantedPage;
			header("Location: /login/");
		} catch (NotFoundException $e) {
			header("HTTP/1.0 404 Not Found");
			ob_end_clean();
			utls::logStr("Uncaught 404 exception: " . $e->getMessage() . "\n" . $e->getTraceAsString());
			//utls::logStr("Uncaught exception: " . $e->getMessage() . "\n" . $e->getTraceAsString());
			echo '<h1>Error 404 catched!</h1><hr/>', "\n",
			'Error: <b>', $e->getMessage(), "</b><br/>\n",
			'Code: ', $e->getCode(), "<br/>\n",
			'File: "', $e->getFile(), '" at ', $e->getLine(), ' line.', "<br/>\n",
			'Trace: <pre>', $e->getTraceAsString(), '</pre>'
			//,'<hr>Debug messages: <pre>', print_r(dbgMsg::dump(), true), '</pre>'
			;
		} catch (Exception $e) {
			ob_end_clean();
			utls::logStr("Uncaught exception: " . $e->getMessage() . "\n" . $e->getTraceAsString());
			//utls::logStr("Uncaught exception: " . $e->getMessage() . "\n" . $e->getTraceAsString());
			echo '<h1>Error catched!</h1><hr/>', "\n",
			'Error: <b>', $e->getMessage(), "</b><br/>\n",
			'Code: ', $e->getCode(), "<br/>\n",
			'File: "', $e->getFile(), '" at ', $e->getLine(), ' line.', "<br/>\n",
			'Trace: <pre>', $e->getTraceAsString(), '</pre>'
			//,'<hr>Debug messages: <pre>', print_r(dbgMsg::dump(), true), '</pre>'
			;
		}
	}



	/**
	 * Выполнятся нормальный способо обработки запроса:
	 *  1. Делается проверка на сервисный вызов;
	 *  2. Если п.1. == да тогда выполнение прерывается;
	 *  3. Выполняются общесайтовые сниппеты;
	 *  4. Если сниппеты не запрещают дальнейшую работу, тогда обработка
	 *  передаётся целевому обработчику запроса.
	 *
	*/
	static protected function executeNormalFlow()
	{
		$commonSnippets = new CommonSnippets();
		$commonSnippets->run();
		if (!$commonSnippets->isOutputPrevented()) {
			$pagehandler = self::getRequestHandler();
			//print_a($pagehandler);
			//echo "run";
			$pagehandler->run();
		}
	}



	/**
	 * Устанавливаем свои обработчики на ошибки и исключения
	 * @todo переименновать
	*/
	static protected function catchExceptions()
	{
		set_error_handler(array(__CLASS__, 'exception_error_handler'), E_ALL ^ E_NOTICE);
//		set_error_handler(array(__CLASS__, 'exception_error_handler'), E_ALL | ~ E_NOTICE);
		set_exception_handler(array(__CLASS__, 'exception_handler'));
	}



	static protected function includeFiles()
	{
		include_once(CARABI_DIR . '/classes/class.utls.php');
		include_once(CARABI_DIR . '/shared.php');
		include_once(CARABI_DIR . '/formz/simpledocument.inc');
		include_once(CARABI_DIR . '/formz/simpledocumentslist.inc');
		//include_once(CARABI_DIR . '/includes/core_url.inc');
		include_once(CARABI_DIR . '/function/utilities.inc');
		//include_once(CARABI_DIR . '/includes/socket_api.php');
	}



	/**
	 * Приводим все ошибки к исклчючениям
	*/
	static public function exception_error_handler($errno, $errstr, $errfile, $errline)
	{
		throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
	}



	/**
	 * Обработчик исключений
	*/
	static public function exception_handler($exception)
	{
		utls::logStr("Caught exception: " . $exception->getMessage() . "\n" . $exception->getTraceAsString());
		echo "Caught exception: " , $exception->getMessage(), "\n";
		//echo '<pre>',print_r($exception->getTrace(), true),'</pre>';
		echo '<pre>', $exception->getTraceAsString(),'</pre>';
		//echo '<hr>', 'Debug messages:', '<pre>', print_r(dbgMsg::dump()), '</pre>';
	}



	/**
	 * Функция автозагрузки файлов классов. Поиск файлов ведётся в папка
	 * определённых в переменной $classLookupDir в конфиге.
	 * Именна файлов должны должны соответствовать: class.<имя класса>.php
	*/
	static protected function autoloader($class_name)
	{
		global $classLookupDir;
		if (!is_array($classLookupDir))
			$classLookupDir = array();
			
		for ($i=0, $j=count($classLookupDir); $i<$j; $i++) {
			$class_file = $classLookupDir[$i] . '/class.' . $class_name . '.php';
			if (is_file($class_file))
				include_once $class_file;
		}
	}
	
	
	static protected function autoloader_namespace($class)
	{
		$path = explode('\\', $class);
		if ('carabi' == strtolower($path[0])) {
			array_shift($path);
		}
		
		global $classLookupDir;
		if (!is_array($classLookupDir))
			$classLookupDir = array();

		$filename = array_pop($path);
		$filenameWithNamespace = implode('/', $path) . '/class.' . $filename . '.php';

		//Большинство classLookupDir выглядят, как "модуль_проекта/classes"
		//Будем смотреть в модуль_проекта/classes/namespace/className и
		//в модуль_проекта/classes/className, если путь выше содержит namespace
		
		for ($i=0, $j=count($classLookupDir); $i<$j; $i++) {
			$fullFilename = $classLookupDir[$i] . '/' . $filenameWithNamespace;
				
			if (!is_file($fullFilename)) {
				//Проверяем $classLookupDir на наличие сегментов namespace
				$namespaceElements = $path;
				$k = 0;
				$n = count($namespaceElements);
				while ($k < $n && strpos($classLookupDir[$i], $namespaceElements[$k]) !== false) {
					array_shift($namespaceElements);
				}
				$fullFilename = $classLookupDir[$i] . '/' . implode('/', $namespaceElements) . '/class.' . $filename . '.php';
				if (!is_file($fullFilename)) {
					continue;
				}
			}

			require_once $fullFilename;
			
			if (!class_exists($class, false))
				return;
				//throw new Exception('No class [' . $class . ']');

			return true;
		}
		
		return;
		
		//throw new Exception('No file [' . $filenameWithNamespace . '] for class [' . $class . ']');
		
	}
	
	
	

	
	/**
	 * Функция возвращает текущий обработчик запроса. Если такого нет, то
	 * предпринемается попытка поиска такового.
	 * Поиск ведётся перебором по списку поисковиков.
	 *
	 * @todo Сделать проверку на интерфейс при выборе поисковика.
	 * @todo Сделать проверку на интерфейс результат поисковика
	 *
	*/
	final static public function getRequestHandler()
	{
		if (!is_object(self::$requestHandler)) {
			for ($i=0, $j=count(self::$requestHandlerFinders); $i<$j; $i++) {
				$className = self::$requestHandlerFinders[$i];
				$requestHandler = $className::getHandler();
				if (is_object($requestHandler)) {
					self::$requestHandler = $requestHandler;
					break;
				}
			}
		}
		return self::$requestHandler;
	}

	final static public function openedWithBot()
	{
		if		(stristr($_SERVER['HTTP_USER_AGENT'], 'yandex'))		$bot='Yandex';
		else if (stristr($_SERVER['HTTP_USER_AGENT'], 'google') )		$bot='Google';
		else if (stristr($_SERVER['HTTP_USER_AGENT'], 'rambler'))		$bot='Rambler';
		else if (stristr($_SERVER['HTTP_USER_AGENT'], 'stack'))			$bot='Rambler2';
		else if (stristr($_SERVER['HTTP_USER_AGENT'], 'yahoo'))			$bot='Yahoo';
		else if (stristr($_SERVER['HTTP_USER_AGENT'], 'aport'))			$bot='Aport';
		else if (stristr($_SERVER['HTTP_USER_AGENT'], 'msnbot'))		$bot='msnbot/1.0';
		else if (stristr($_SERVER['HTTP_USER_AGENT'], 'ia_archiver'))	$bot='Alexa search engine';
		else if (stristr($_SERVER['HTTP_USER_AGENT'], 'scooter'))		$bot='AltaVista';
		else if (stristr($_SERVER['HTTP_USER_AGENT'], 'lycos'))			$bot='Lycos';
		else if (stristr($_SERVER['HTTP_USER_AGENT'], 'WebAlta'))		$bot='WebAlta';
		else $bot = null;
		return $bot;
	}

	/**
	 * 
	 * @return Smarty
	 */
	final static public function getRenderer() {
		if (!self::$renderer) {
			self::$renderer = new carabiSmarty();
			//$this->renderer->smarty->addTemplateDir(PROJECT_DIR.'/smarty/tmplt');
			//$this->renderer->smarty->addPluginsDir(PROJECT_DIR.'/smarty/plugins');
			
			self::$renderer->assignByRef('pagehandler', self::$requestHandler);
		}
		return self::$renderer;
	}
	
	
	final static public function getRequestUrl()
	{
		return $_SERVER['REDIRECT_URL'];
	}


}

?>