<?php
namespace Bitrix\Main;

/**
 * Represents server. Singleton.
 */
final class Server
{
	/**
	 * @var Server
	 */
	private static $instance = null;

	/**
	 * @var array
	 */
	private $arServerParameters = array();

	/**
	 * @var Application
	 */
	private $application = null;

	/**
	 * Creates server object.
	 * Can't be called directly, use start() instead.
	 *
	 * @param array $arServerParameters
	 */
	private function __construct($arServerParameters)
	{
		$this->arServerParameters = $arServerParameters;

		if (isset($this->arServerParameters["DOCUMENT_ROOT"]))
			$this->arServerParameters["DOCUMENT_ROOT"] = rtrim($this->arServerParameters["DOCUMENT_ROOT"], "\\/");

		$this->application = null;
	}

	/**
	 * Returns current instance of the server.
	 * Server should be previously started by start()
	 *
	 * @throws SystemException
	 * @return Server
	 */
	public static function getInstance()
	{
		if (!isset(self::$instance))
			throw new SystemException("Application server is not started");

		return self::$instance;
	}

	/**
	 * Starts server and returns its instance. Can be called only once.
	 * Use getInstance() to get server instance after server was started.
	 *
	 * @param array $arServerParameters
	 * @throws SystemException
	 * @return Server
	 */
	public static function start($arServerParameters)
	{
		if (isset(self::$instance))
			throw new SystemException("Application server is already started");

		$c = __CLASS__;
		return self::$instance = new $c($arServerParameters);
	}

	/**
	 * Returns instance of current Application. Creates instance if necessary.
	 *
	 * @return Application
	 */
	public function getApplication()
	{
		if ($this->application == null)
			$this->application = new HttpApplication($this);

		return $this->application;
	}

	/**
	 * Returns server document root.
	 *
	 * @return string | null
	 */
	public function getDocumentRoot()
	{
		return $this->arServerParameters["DOCUMENT_ROOT"];
	}

	/**
	 * Modifies server document root.
	 *
	 * @param string $documentRoot
	 */
	public function setDocumentRoot($documentRoot)
	{
		$this->arServerParameters["DOCUMENT_ROOT"] = $documentRoot;
	}

	/**
	 * Returns server http host.
	 *
	 * @return string | null
	 */
	public function getHttpHost()
	{
		return $this->arServerParameters["HTTP_HOST"];
	}

	/**
	 * Returns server name.
	 *
	 * @return string | null
	 */
	public function getServerName()
	{
		return $this->arServerParameters["SERVER_NAME"];
	}

	/**
	 * Returns server address.
	 *
	 * @return string | null
	 */
	public function getServerAddr()
	{
		return $this->arServerParameters["SERVER_ADDR"];
	}

	/**
	 * Returns server port.
	 *
	 * @return string | null
	 */
	public function getServerPort()
	{
		return $this->arServerParameters["SERVER_PORT"];
	}

	/**
	 * Returns requested uri.
	 *
	 * @return string | null
	 */
	public function getRequestUri()
	{
		return $this->arServerParameters["REQUEST_URI"];
	}

	/**
	 * Returns requested method.
	 *
	 * @return string | null
	 */
	public function getRequestMethod()
	{
		return $this->arServerParameters["REQUEST_METHOD"];
	}

	/**
	 * Returns user agent of the current request.
	 *
	 * @return string | null
	 */
	public function getUserAgent()
	{
		return $this->arServerParameters["HTTP_USER_AGENT"];
	}

	/**
	 * Returns accepted languages of the current request.
	 *
	 * @return string | null
	 */
	public function getAcceptedLanguages()
	{
		return $this->arServerParameters["HTTP_ACCEPT_LANGUAGE"];
	}

	/**
	 * Returns PHP_SELF.
	 *
	 * @return string | null
	 */
	public function getPhpSelf()
	{
		return $this->arServerParameters["PHP_SELF"];
	}

	/**
	 * Returns SCRIPT_NAME.
	 *
	 * @return string | null
	 */
	public function getScriptName()
	{
		return $this->arServerParameters["SCRIPT_NAME"];
	}

	/**
	 * Returns custom root folder.
	 * Server variable BX_PERSONAL_ROOT is used. If empty - returns /bitrix.
	 *
	 * @return string | null
	 */
	public function getPersonalRoot()
	{
		if (isset($this->arServerParameters["BX_PERSONAL_ROOT"]) && $this->arServerParameters["BX_PERSONAL_ROOT"] != "")
			return $this->arServerParameters["BX_PERSONAL_ROOT"];

		return "/bitrix";
	}

	/**
	 * Returns any server variable by its name. Null if variable is not set.
	 *
	 * @param string $name
	 * @return string | null
	 */
	public function get($name)
	{
		if (isset($this->arServerParameters[$name]))
			return $this->arServerParameters[$name];

		return null;
	}

	/**
	 * Returns true id server is in utf-8 mode. False - otherwise.
	 *
	 * @return bool
	 */
	public function isUtfMode()
	{
		static $isUtfMode = null;
		if ($isUtfMode === null)
		{
			$isUtfMode = \Bitrix\Main\Config\Configuration::getValue("utf_mode");
			if ($isUtfMode === null)
				$isUtfMode = false;
		}
		return $isUtfMode;
	}

	/**
	 * Returns server document root. Static alias of method getDocumentRoot.
	 *
	 * @return null|string
	 */
	public static function getRoot()
	{
		$server = self::getInstance();
		return $server->getDocumentRoot();
	}

	/**
	 * Resets accelerator if any.
	 */
	public static function resetAccelerator()
	{
		$fl = \Bitrix\Main\Config\Configuration::getValue("NoAcceleratorReset");
		if ($fl)
			return;

		if (function_exists("accelerator_reset"))
			accelerator_reset();
		elseif (function_exists("wincache_refresh_if_changed"))
			wincache_refresh_if_changed();
	}
}
