<?php

/**
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @package clearFusionCMS
 * @copyright Copyright (c) 2012 - 2017 clearFusionCMS. All rights reserved.
 * @link http://clearfusioncms.com
 */

/**
 * clearFusionCMS Class
 *
 * Static clearFusionCMS application class.
 *
 * @package clearFusionCMS
 */
class clearFusionCMS extends flApp {
	/**
	 * The user object.
	 *
	 * @var flUser
	 */
	protected $user = null;

	/**
	 * The user manager object.
	 *
	 * @var flUserMgr
	 */
	protected $userMgr = null;

	/**
	 * The short name of the active site.
	 *
	 * @var string
	 */
	protected $site = null;

	/**
	 * The display name of the active site.
	 *
	 * @var string
	 */
	protected $siteName = null;

	/**
	 * The twitter account attributed to the site.
	 *
	 * @var string
	 */
	protected $siteTwitter = '';

	/**
	 * Flags if site is only accessible via SSL.
	 *
	 * @var bool
	 */
	protected $sslOnly = false;

	/**
	 * The timezone.
	 *
	 * @var string
	 */
	protected $timezone = null;

	/**
	 * The system timezone.
	 *
	 * @var string
	 */
	protected $sysTZ = null;

	/**
	 * Cache of flConfig objects.
	 *
	 * @var array
	 */
	protected $configs = array();

	/**
	 * Cache of task data.
	 *
	 * @var array
	 */
	protected $taskData = array();

	/**
	 * Get the instance of the application object.
	 *
	 * @return clearFusionCMS|flApp The app instance.
	 */
	static function getInstance() {
		return self::$instance !== null ? self::$instance : self::$instance = new clearFusionCMS();
	}

	/**
	 * Disable any cache systems.
	 */
	static function disableCache() {
		self::getInstance()->cache = new flCacheDummy();
	}

	/**
	 * Get the user object.
	 *
	 * @return flUser The object describing the user.
	 */
	static function getUser() {
		$instance = self::getInstance();
		if($instance->user === null) {
			flUser::setCookieInfo($instance->cfg->get('authCookieName', '__userid'), $instance->cfg->get('authCookieDomain', ''), $instance->cfg->get('authCookiePath', '/'), $instance->secureCookies);
			$cls = $instance->cfg->get('userAdapter', 'flUserAdapter');
			$instance->user = new flUser($instance->db, $instance->request, $instance->response, new $cls($instance->db, $instance->cfg));
		}
		return $instance->user;
	}

	/**
	 * Get the access control object.
	 *
	 * @return flUser The object for testing permissions or false if the user is not authenticated.
	 * @deprecated Applications should use getUser
	 */
	static function getAccessCtrl() {
		$instance = self::getInstance();
		$user = $instance->getUser();
		return $user->isAuthenticated() ? $user : false;
	}

	/**
	 * Get the user manager object.
	 *
	 * @return flUserMgr The user manager object.
	 */
	static function getUserMgr() {
		$instance = self::getInstance();
		if($instance->userMgr === null)
			$instance->userMgr = new flUserMgr($instance->db, $instance->getUser()->getAdapter());
		return $instance->userMgr;
	}

	/**
	 * Set the name of the active site.
	 *
	 * @param string $site The short name of the active site.
	 * @param string $displayName The display name of the active site.
	 * @param string $twitterAccount The twitter account attributed to the site.
	 * @param bool $sslOnly Flags if the site is accessible only via SSL.
	 */
	static function setSite($site, $displayName, $twitterAccount = '', $sslOnly = false) {
		$instance = self::getInstance();
		$instance->site = $site;
		$instance->siteName = $displayName;
		$instance->siteTwitter = empty($twitterAccount) ? '' :  '@' . $twitterAccount;
		$instance->sslOnly = $instance->secureCookies = $sslOnly;

		// If Site is SSL and request is not SSL then force browser to the SSL version of the site
		if($sslOnly && !clearFusionCMS::getRequest()->isSecure())
			clearFusionCMS::getResponse()->redirectTo(clearFusionCMS::getRequest()->getSelf(true, true), true);
	}

	/**
	 * Get the name of the active site.
	 *
	 * @return string The short name of the active site.
	 */
	static function getSite() {
		return self::getInstance()->site;
	}

	/**
	 * Get the display name of the active site.
	 *
	 * @return string The display name of the active site.
	 */
	static function getSiteName() {
		return self::getInstance()->siteName;
	}

	/**
	 * Get the twitter account that the site is attibuted to.
	 *
	 * @return string The twitter account the site is attributed to.
	 */
	static function getSiteTwitter() {
		return self::getInstance()->siteTwitter;
	}

	/**
	 * Get if the site is SSL only.
	 *
	 * @param bool $default The default value to return if the site is no SSL only.
	 * @return bool true if the site is SSL only else the default value.
	 */
	static function getSiteSSL($default = false) {
		return self::getInstance()->sslOnly ? true : $default;
	}

	/**
	 * Get the timezone.
	 *
	 * @return string If a user is logged in then their timezone; else the system timezone.
	 */
	static function getTimezone() {
		$instance = self::getInstance();
		if($instance->timezone === null) {
			if(self::getUser()->isAuthenticated())
				$instance->timezone = $instance->user->getTimezone();
			else
				$instance->timezone = $instance->getSysTimezone();
		}
		return $instance->timezone;
	}

	/**
	 * Get the timezone used for the system.
	 *
	 * @return string The system timezone.
	 */
	static function getSysTimezone() {
		$instance = self::getInstance();
		if($instance->sysTZ === null) {
			$cfg = $instance->getSiteConfig('cfSystemTZ');
			$instance->sysTZ = $cfg->timezone;
		}
		return $instance->sysTZ;
	}

	/**
	 * Get the site configuration object for a given namespace.
	 *
	 * @param string $namespace The namespace to get the config for.
	 * @return flConfig The configuration object.
	 * @throws clearFusionCMSException
	 */
	static function getSiteConfig($namespace) {
		$instance = self::getInstance();
		if($instance->site === null)
			throw new clearFusionCMSException('Unable to return a site configuration namespace as the site name has not been set.');
		if(!isset($instance->configs[$namespace]))
			$instance->configs[$namespace] = new flConfigDb($namespace, $instance->db, 'cf_config_' . $instance->site);
		return $instance->configs[$namespace];
	}

	/**
	 * Get a mailer object to send system emails from with the sender and reply to addresses set from the site config.
	 *
	 * @return flEmail The mailer object.
	 */
	static function getMailer() {
		$systemCfg = clearFusionCMS::getSiteConfig('cfSystemEmail');

		$mailer = new flEmail();
		$mailer->setLocalhost(clearFusionCMS::getRequest()->getServerName())
			->setFrom($systemCfg->sysEmail)
			->replyTo($systemCfg->sysEmail);

		if(!empty($systemCfg->smtpServer))
			$mailer->setServer($systemCfg->smtpServer, $systemCfg->smtpPort, $systemCfg->smtpUser, $systemCfg->smtpPass);

		return $mailer;
	}

	/**
	 * Get the data object for a task.
	 *
	 * @param string $taskName The name name of the task to get the data for.
	 * @return flVariables The data.
	 * @throws clearFusionCMSException
	 */
	static function getTaskData($taskName) {
		$instance = self::getInstance();
		if(!isset($instance->taskData[$taskName])) {
			if($instance->db->fetchOne('SELECT COUNT(*) FROM cf_tasksnippets WHERE taskname=?', $taskName))
				$instance->taskData[$taskName] = new flVariables('cfTask.' . $taskName, $instance->db);
			else
				throw new clearFusionCMSException("Unable to return task data for unknown task '$taskName'.");
		}
		return $instance->taskData[$taskName];
	}

	/**
	 * Send out a system notification event.
	 *
	 * @param int $level The level 1 through 5, 1 being the lowest.
	 * @param string $message The text formatted message to send.
	 * @param string $mention The list of users to mention.
	 *
	 * @deprecated
	 * @see cfEventNotify
	 */
	static function notify($level, $message, $mention = '') {
		if($level) self::getEventManager()->notify(new flEvent('system.notify', array('level' => $level, 'message' => $message, 'mention' => $mention)));
	}
}
