<?php
abstract class vB5_ApplicationAbstract {
	protected static $instance;
	protected $router = NULL;

	public static function instance()
	{
		if (!isset(self::$instance))
		{
			throw new vB5_Exception('Application hasn\'t been initialized!');
		}

		return self::$instance;
	}

	public static function init($configFile)
	{
		$config = vB5_Config::instance();
		$config->loadConfigFile($configFile);

		self::ajaxCharsetConvert();
		set_exception_handler(array('vB5_ApplicationAbstract','handleException'));
		set_error_handler(array('vB5_ApplicationAbstract','handleError'),E_WARNING );
	}

	public function getRouter()
	{
		return $this->router;
	}

	/**
	 * @static
	 * When current lang charset isn't the one in http content_type header
	 * this method will convert All Ajax $_POST data into current language charset
	 */
	protected static function ajaxCharsetConvert() {
		$requestcharset = '';
		if (isset($_SERVER["CONTENT_TYPE"]) AND $_SERVER["CONTENT_TYPE"])
		{
			if (($pos = strpos(strtoupper($_SERVER["CONTENT_TYPE"]), 'CHARSET')) !== false)
			{
				$requestcharset = substr(strtoupper($_SERVER["CONTENT_TYPE"]), $pos);
				$temp = explode('=', $requestcharset);
				if (!empty($temp[1]))
				{
					$requestcharset = trim($temp[1]);
				}
			}
		}
		if ($requestcharset	AND vB5_String::getTempCharset() != $requestcharset)
		{
			$_POST = vB5_String::toCharset($_POST, $requestcharset);
		}
	}

	/*** Displays a vB page for exceptions
	*
	*	@param	mixed 	exception
	*
	*
	***/
	public static function handleException($exception)
	{
		$config = vB5_Config::instance();

		if ($config->debug)
		{
			$message = $exception->getMessage();
			$api = Api_InterfaceAbstract::instance();
			$phrase = $api->callApi('phrase', 'fetch', array('phrase' => $message));

			if (!empty($phrase))
			{
				$message = $phrase;
			}
			$error = array('message' => $message,
				'file' => $exception->getFile(),
				'line' => $exception->getLine(),
				'trace' => $exception->getTrace()
			);
		}
		else
		{
			$error = false;
		}

		self::showErrorPage($error);
		die();
	}

	/*** Displays a vB page for no_permission exception
	*
	*	@param	mixed 	exception
	*
	*
	***/
	public static function handleNoPermission()
	{
		self::showNoPermissionPage();
		die();
	}

	/*** Displays a vB page for banned users
	*
	*	@param	mixed 	exception
	*
	*
	***/
	public static function handleBannedUsers($bannedInfo)
	{
		self::showBannedPage($bannedInfo);
		die();
	}

	/*** Displays a vB page for errors
	 *
	 *	@param	string	error number
	 *	@param	string	error message
	 *	@param	string	filename
	 *	@param	string	line number
	 *
	 *
	 ***/
	public static function handleError($errno, $errstr, $errfile, $errline, $errcontext)
	{
		// Explain to (strpos($errfile, 'includes\vb5\template\runtime.php') === false) condition:
		//   Now the eval() in vB5_Template::render() method won't throw any errors because of the prepended @ operator
		//   To catch the error of the template, we check if the error is thrown by runtime.php
		//   If so, regardless the error_reporting() value, we report the error.
		if (!(error_reporting() & $errno) AND strpos($errfile, 'includes\vb5\template\runtime.php') === false) {
			// This error code is not included in error_reporting
			return;
		}
		//for warning, notices, etc
		$config = vB5_Config::instance();
		if ($config->debug)
		{
			$error = array('message' => $errstr,
				'file' => $errfile,
				'line' => $errline,
			'trace' => debug_backtrace());
		}
		else
		{
			$error = false;
		}

		self::showErrorPage($error);
		die();
	}

	protected static function showErrorPage($error)
	{
		//We want the simplest possible page.
		$templater = new vB5_Template('error_page');

		$router = vB5_ApplicationAbstract::instance()->getRouter();
		$arguments = $router->getArguments();
		$page = array();
		$page['routeInfo'] = array(
			'routeId' => $router->getRouteId(),
			'arguments' => $arguments,
			'queryParameters' => $router->getQueryParameters()
		);
		$page['ignore_np_notices'] = isset($_COOKIE[vB5_Config::instance()->cookie_prefix . 'np_notices_displayed']) ?
			explode(',', $_COOKIE[vB5_Config::instance()->cookie_prefix . 'np_notices_displayed']) : array();
		$templater->register('page', $page);
		$templater->register('error', $error);
		echo $templater->render();
	}

	public static function handleForumClosed($controller = '', $action = '')
	{
		if (!vB::getDatastore()->getOption('bbactive') AND !vB::getUserContext()->isAdministrator())
		{
			if (strtolower($controller) == 'auth')
			{
				return;
			}
			self::showNoPermissionPage(vB::getDatastore()->getOption('bbclosedreason'), '');
			die();
		}
	}

	protected static function showNoPermissionPage($message = '')
	{
		//We want the simplest possible page.
		$templater = new vB5_Template('no_permission_page');

		$router = vB5_ApplicationAbstract::instance()->getRouter();
		$arguments = $router->getArguments();
		$page = array();
		$page['routeInfo'] = array(
			'routeId' => $router->getRouteId(),
			'arguments' => $arguments,
			'queryParameters' => $router->getQueryParameters()
		);
		$page['ignore_np_notices'] = isset($_COOKIE[vB5_Config::instance()->cookie_prefix . 'np_notices_displayed']) ?
			explode(',', $_COOKIE[vB5_Config::instance()->cookie_prefix . 'np_notices_displayed']) : array();
		$templater->register('message', $message);
		$templater->register('page', $page);
		echo $templater->render();
	}

	protected static function showBannedPage($bannedInfo)
	{
		//We want the simplest possible page.
		$templater = new vB5_Template('banned_page');

		$router = vB5_ApplicationAbstract::instance()->getRouter();
		$arguments = $router->getArguments();
		$page = array();
		$page['routeInfo'] = array(
			'routeId' => $router->getRouteId(),
			'arguments' => $arguments,
			'queryParameters' => $router->getQueryParameters()
		);
		$page['ignore_np_notices'] = isset($_COOKIE[vB5_Config::instance()->cookie_prefix . 'np_notices_displayed']) ?
			explode(',', $_COOKIE[vB5_Config::instance()->cookie_prefix . 'np_notices_displayed']) : array();
		$templater->register('page', $page);
		$templater->register('bannedInfo', $bannedInfo);

		echo $templater->render();
	}

}
