<?php
if (!defined("ROOT_PATH"))
{
	header("HTTP/1.1 403 Forbidden");
	exit;
}
class pjAppController extends pjController
{
	public $models = array();

	public $defaultLocale = 'admin_locale_id';
	
	public $defaultFields = 'fields';
	
	public $defaultFieldsIndex = 'fields_index';
	
	public $defaultTheme = 'front_theme_id';
	
	protected function loadSetFields($force=FALSE)
	{
		$registry = pjRegistry::getInstance();
		if ($force
				|| !isset($_SESSION[$this->defaultFieldsIndex])
				|| $_SESSION[$this->defaultFieldsIndex] != $this->option_arr['o_fields_index']
				|| !isset($_SESSION[$this->defaultFields])
				|| empty($_SESSION[$this->defaultFields]))
		{
			pjAppController::setFields($this->getLocaleId());
	
			# Update session
			if ($registry->is('fields'))
			{
				$_SESSION[$this->defaultFields] = $registry->get('fields');
			}
			$_SESSION[$this->defaultFieldsIndex] = $this->option_arr['o_fields_index'];
		}
	
		if (isset($_SESSION[$this->defaultFields]) && !empty($_SESSION[$this->defaultFields]))
		{
			# Load fields from session
			$registry->set('fields', $_SESSION[$this->defaultFields]);
		}

		if (pjObject::getPlugin('pjWebsiteContent') !== NULL)
		{
			pjWebsiteContent::pjActionInit();
		}
	
		return TRUE;
	}
	
	public static function setTimezone($timezone="UTC")
    {
    	if (in_array(version_compare(phpversion(), '5.1.0'), array(0,1)))
		{
			date_default_timezone_set($timezone);
		} else {
			$safe_mode = ini_get('safe_mode');
			if ($safe_mode)
			{
				putenv("TZ=".$timezone);
			}
		}
    }

	public static function setMySQLServerTime($offset="-0:00")
    {
		pjAppModel::factory()->prepare("SET SESSION time_zone = :offset;")->exec(compact('offset'));
    }
    
	public function setTime()
	{
		if (isset($this->option_arr['o_timezone']))
		{
			$offset = $this->option_arr['o_timezone'] / 3600;
			if ($offset > 0)
			{
				$offset = "-".$offset;
			} elseif ($offset < 0) {
				$offset = "+".abs($offset);
			} elseif ($offset === 0) {
				$offset = "+0";
			}
	
			pjAppController::setTimezone('Etc/GMT' . $offset);
			if (strpos($offset, '-') !== false)
			{
				$offset = str_replace('-', '+', $offset);
			} elseif (strpos($offset, '+') !== false) {
				$offset = str_replace('+', '-', $offset);
			}
			pjAppController::setMySQLServerTime($offset . ":00");
		}
	}
    
	public function afterFilter()
	{
		if ($_GET['controller'] != 'pjInstaller')
		{
			$this->set('menu_locale_arr', pjLocaleModel::factory()->select('t1.*, t2.file, t2.title')
				->join('pjLocaleLanguage', 't2.iso=t1.language_iso', 'left outer')
				->where('t2.file IS NOT NULL')
				->orderBy('t1.sort ASC')
				->findAll()
				->getDataPair('id')
			);
		}
	}
	
    public function beforeFilter()
    {
    	$this->appendJs('jquery.min.js', PJ_THIRD_PARTY_PATH . 'jquery/');
    	$baseDir = defined("PJ_INSTALL_PATH") ? PJ_INSTALL_PATH : NULL;
    	$dm = new pjDependencyManager($baseDir, PJ_THIRD_PARTY_PATH);
    	$dm->load(PJ_CONFIG_PATH . 'dependencies.php')->resolve();
    	$this->appendJs('jquery-migrate.min.js', $dm->getPath('jquery_migrate'), FALSE, FALSE);
    	$this->appendJs('pjAdminCore.js');
    	$this->appendCss('reset.css');
    	
    	$this->appendJs('js/jquery-ui.custom.min.js', PJ_THIRD_PARTY_PATH . 'jquery_ui/');
		$this->appendCss('css/smoothness/jquery-ui.min.css', PJ_THIRD_PARTY_PATH . 'jquery_ui/');
				
		$this->appendCss('pj-all.css', PJ_FRAMEWORK_LIBS_PATH . 'pj/css/');
		$this->appendCss('admin.css');
		
    	if ($_GET['controller'] != 'pjInstaller')
		{
			$this->models['Option'] = pjOptionModel::factory();
			$this->option_arr = $this->models['Option']->getPairs($this->getForeignId());
			$this->set('option_arr', $this->option_arr);
			$this->setTime();
    
			if (!isset($_SESSION[$this->defaultLocale]))
			{
				$locale_arr = pjLocaleModel::factory()->where('is_default', 1)->limit(1)->findAll()->getData();
				if (count($locale_arr) === 1)
				{
					$this->setLocaleId($locale_arr[0]['id']);
				}
			}
			$this->loadSetFields();
		}
    }
    
    public function getForeignId()
    {
    	return 1;
    }
    
    public static function getEmailTokens($booking_arr, $listing_arr, $option_arr)
    {
    	$payment_methods = __('payment_methods', true);
    	$cancelURL = PJ_INSTALL_URL . 'index.php?controller=pjListings&action=pjActionCancel&id='.@$booking_arr['id'].'&hash='.sha1(@$booking_arr['id'].@$booking_arr['created']);
    	$cancelURL = '<a href="'.$cancelURL.'">' . $cancelURL . '</a>';
    	
    	$start_date = isset($booking_arr['date_from']) ? date($option_arr['o_date_format'], strtotime($booking_arr['date_from'])) : NULL;
    	$end_date = isset($booking_arr['date_to']) ? date($option_arr['o_date_format'], strtotime($booking_arr['date_to'])) : NULL;
    	
    	$search = array(
			'{Name}', '{Email}', '{Phone}', '{Notes}',
			'{CCType}', '{CCNum}', '{CCExp}', '{CCSec}',
			'{PaymentMethod}', '{ListingID}', '{ListingRefID}',
			'{StartDate}', '{EndDate}', '{ReservationID}', '{ReservationUUID}',
			'{Deposit}', '{Price}', '{Tax}', '{Security}', '{Total}', '{CancelURL}');
		$replace = array(
			@$booking_arr['name'], @$booking_arr['email'], @$booking_arr['phone'], @$booking_arr['notes'],
			@$booking_arr['cc_type'], @$booking_arr['cc_num'], (@$booking_arr['payment_method'] == 'creditcard' ? @$booking_arr['cc_exp'] : NULL), @$booking_arr['cc_code'],
			@$payment_methods[$booking_arr['payment_method']], @$booking_arr['listing_id'], @$listing_arr['listing_refid'],
			$start_date, $end_date, @$booking_arr['id'], @$booking_arr['uuid'],
			@$booking_arr['deposit'] . " " . @$option_arr['o_currency'], @$booking_arr['amount'] . " " . @$option_arr['o_currency'], @$booking_arr['tax'] . " " . @$option_arr['o_currency'], @$booking_arr['security'] . " " . @$option_arr['o_currency'], (@$booking_arr['amount'] + @$booking_arr['security'] + @$booking_arr['tax']) . " " . @$option_arr['o_currency'],
				$cancelURL
		);
		return compact('search', 'replace');
    }
    
    public static function setFields($locale)
    {
    	if(isset($_SESSION['lang_show_id']) && (int) $_SESSION['lang_show_id'] == 1)
		{
			$fields = pjMultiLangModel::factory()
				->select('CONCAT(t1.content, CONCAT(":", t2.id, ":")) AS content, t2.key')
				->join('pjField', "t2.id=t1.foreign_id", 'inner')
				->where('t1.locale', $locale)
				->where('t1.model', 'pjField')
				->where('t1.field', 'title')
				->findAll()
				->getDataPair('key', 'content');
		}else{
			$fields = pjMultiLangModel::factory()
				->select('t1.content, t2.key')
				->join('pjField', "t2.id=t1.foreign_id", 'inner')
				->where('t1.locale', $locale)
				->where('t1.model', 'pjField')
				->where('t1.field', 'title')
				->findAll()
				->getDataPair('key', 'content');
		}
		$registry = pjRegistry::getInstance();
		$tmp = array();
		if ($registry->is('fields'))
		{
			$tmp = $registry->get('fields');
		}
		$arrays = array();
		foreach ($fields as $key => $value)
		{
			if (strpos($key, '_ARRAY_') !== false)
			{
				list($prefix, $suffix) = explode("_ARRAY_", $key);
				if (!isset($arrays[$prefix]))
				{
					$arrays[$prefix] = array();
				}
				$arrays[$prefix][$suffix] = $value;
			}
		}
		require PJ_CONFIG_PATH . 'settings.inc.php';
		$fields = array_merge($tmp, $fields, $settings, $arrays);
		$registry->set('fields', $fields);
    }

    public static function jsonDecode($str)
	{
		$Services_JSON = new pjServices_JSON();
		return $Services_JSON->decode($str);
	}
	
	public static function jsonEncode($arr)
	{
		$Services_JSON = new pjServices_JSON();
		return $Services_JSON->encode($arr);
	}
	
	public static function jsonResponse($arr)
	{
		header("Content-Type: application/json; charset=utf-8");
		echo pjAppController::jsonEncode($arr);
		exit;
	}

	public function isEditor()
	{
		return $this->getRoleId() == 2;
	}

	public function isOwner()
	{
		return $this->getRoleId() == 3;
	}
	
	public function isDrawSearchReady()
	{
		return $this->isAdmin();
	}
	
	public function isCountryReady()
	{
		return $this->isAdmin();
	}
	
	public function isWebsiteContentReady()
	{
		return $this->isAdmin();
	}

	public function isContactFormReady()
	{
		return $this->isAdmin();
	}
	public function isOneAdminReady()
	{
		return $this->isAdmin();
	}
	public function getLocaleId()
	{
		return isset($_SESSION[$this->defaultLocale]) && (int) $_SESSION[$this->defaultLocale] > 0 ? (int) $_SESSION[$this->defaultLocale] : false;
	}
	
	public function setLocaleId($locale_id)
	{
		$_SESSION[$this->defaultLocale] = (int) $locale_id;
	}
	
	public function setTheme($theme)
	{
		$_SESSION[$this->defaultTheme] = $theme;
	}
	
	public function getTheme()
	{
		return isset($_SESSION[$this->defaultTheme]) && !empty($_SESSION[$this->defaultTheme]) ? $_SESSION[$this->defaultTheme] : false;
	}
		
	public function friendlyURL($str, $divider='-')
	{
		$str = mb_strtolower($str, mb_detect_encoding($str)); // change everything to lowercase
		$str = trim($str); // trim leading and trailing spaces
		$str = preg_replace('/[_|\s]+/', $divider, $str); // change all spaces and underscores to a hyphen
		$str = preg_replace('/\x{00C5}/u', 'AA', $str);
		$str = preg_replace('/\x{00C6}/u', 'AE', $str);
		$str = preg_replace('/\x{00D8}/u', 'OE', $str);
		$str = preg_replace('/\x{00E5}/u', 'aa', $str);
		$str = preg_replace('/\x{00E6}/u', 'ae', $str);
		$str = preg_replace('/\x{00F8}/u', 'oe', $str);
		$str = preg_replace('/[^a-z\x{0400}-\x{04FF}0-9-]+/u', '', $str); // remove all non-cyrillic, non-numeric characters except the hyphen
		$str = preg_replace('/[-]+/', $divider, $str); // replace multiple instances of the hyphen with a single instance
		$str = preg_replace('/^-+|-+$/', '', $str); // trim leading and trailing hyphens
		return $str;
	}

	public function notify($notification_id, $user_id=NULL, $params=array())
	{
		$map = array(
			1 => array('o_email_new_user_subject', 'o_email_new_user', 'o_sms_new_user'),
			2 => array('o_email_new_property_subject', 'o_email_new_property', 'o_sms_new_property'),
			3 => array('o_email_new_reservation_subject', 'o_email_new_reservation', 'o_sms_new_reservation'),
			4 => array('o_email_new_reservation_subject', 'o_email_new_reservation', 'o_sms_new_reservation'),
			5 => array('o_email_reservation_cancelled_subject', 'o_email_reservation_cancelled', 'o_sms_reservation_cancelled'),
			6 => array('o_email_reservation_cancelled_subject', 'o_email_reservation_cancelled', 'o_sms_reservation_cancelled')
		);
		
		$pjUserNotificationModel = pjUserNotificationModel::factory()
			->select('t1.type, t2.email, t2.phone')
			->join('pjUser', "t2.id=t1.user_id AND t2.status='T'", 'inner')
			->where('t1.notification_id', $notification_id);

		if (!is_null($user_id))
		{
			$pjUserNotificationModel->where('t1.user_id', $user_id);
		}
		$recipients = $pjUserNotificationModel->findAll()->getData();
		
		$pjEmail = new pjEmail();
		$smsPlugin = (pjObject::getPlugin('pjSms') !== NULL);
		
		$tokens = pjAppController::getEmailTokens($params, $params, $this->option_arr);
		$from_email = $this->getFromEmail($this->option_arr);
		foreach ($recipients as $recipient)
		{
			switch ($recipient['type'])
			{
				case 'email':
					if (empty($recipient['email']))
					{
						continue;
					}
					if ($this->option_arr['o_send_email'] == 'smtp')
					{
						$pjEmail
							->setTransport('smtp')
							->setSmtpHost($this->option_arr['o_smtp_host'])
							->setSmtpPort($this->option_arr['o_smtp_port'])
							->setSmtpUser($this->option_arr['o_smtp_user'])
							->setSmtpPass($this->option_arr['o_smtp_pass'])
							->setSender($this->option_arr['o_smtp_user'])
						;
					}
					
					$body = $this->option_arr[@$map[$notification_id][1]];
					switch ($notification_id)
					{
						case 1:
							$body = str_replace(array('{Name}', '{Email}'), array(@$params['name'], @$params['email']), $body);
							break;
						case 2:
							$body = str_replace(array('{PropertyID}', '{RefID}'), array(@$params['property_id'], @$params['listing_refid']), $body);
							break;
						case 3:
						case 4:
							$body = str_replace($tokens['search'], $tokens['replace'], $body);
							break;
						default:
							$body = str_replace(array('{ReservationID}'), array(@$params['reservation_id']), $body);
							break;
					}
					$body = pjUtil::textToHtml($body);
					$pjEmail
						->setContentType('text/html')
						->setFrom($from_email)
						->setTo($recipient['email'])
						->setSubject($this->option_arr[@$map[$notification_id][0]])
						->send($body);
					break;
				case 'sms':
					if (empty($recipient['phone']) || !$smsPlugin)
					{
						continue;
					}
					$this->requestAction(array(
						'controller' => 'pjSms',
						'action' => 'pjActionSend',
						'params' => array(
							'number' => $recipient['phone'],
							'text' => $this->option_arr[@$map[$notification_id][2]],
							'key' => md5($this->option_arr['private_key'] . PJ_SALT)
						)
					), array('return'));
					break;
			}
		}
	}

	public function pjActionCheckInstall()
	{
		$this->setLayout('pjActionEmpty');
		
		$result = array('status' => 'OK', 'code' => 200, 'text' => 'Operation succeeded', 'info' => array());
		$folders = array();
		foreach ($folders as $dir)
		{
			if (!is_writable($dir))
			{
				$result['status'] = 'ERR';
				$result['code'] = 101;
				$result['text'] = 'Permission requirement';
				$result['info'][] = sprintf('Folder \'<span class="bold">%1$s</span>\' is not writable. You need to set write permissions (chmod 777) to directory located at \'<span class="bold">%1$s</span>\'', $dir);
			}
		}
		
		return $result;
	}
	public function getFromEmail($option_arr)
	{
		$email = $option_arr['o_email_address'];
		if($email == '')
		{
			$arr = pjUserModel::factory()
			->findAll()
			->orderBy("t1.id ASC")
			->limit(1)
			->getData();
			$email = !empty($arr) ? $arr[0]['email'] : null;
		}
		return $email;
	}
	public function getAdminEmail()
	{
		$arr = pjUserModel::factory()
			->findAll()
			->orderBy("t1.id ASC")
			->limit(1)
			->getData();
		return !empty($arr) ? $arr[0]['email'] : null;
	}
	
	public function pjActionGetPrices($data)
	{
		$listing_arr = pjListingModel::factory()->find($data['listing_id'])->getData();
		$p_from = strtotime($data['date_from']);
		$p_to = strtotime($data['date_to']);
	
		$amount = pjPriceModel::factory()->getPrice($p_from, $p_to, $listing_arr['id'], $listing_arr['o_price_based_on']);
		$total = $deposit = $security = $tax = 0;
		if ($amount > 0)
		{
			$security = (float) $listing_arr['o_security_payment'];
			$tax = 0;
			switch ($listing_arr['o_tax_type'])
			{
				case 1:
					$tax = $listing_arr['o_tax_payment'];
					break;
				case 2:
					$tax = ($amount * $listing_arr['o_tax_payment']) / 100;
					break;
			}
			if (isset($listing_arr['o_require_all_within_days'])
					&& (int) $listing_arr['o_require_all_within_days'] > 0
					&& strtotime(date("Y-m-d")) + (int) $listing_arr['o_require_all_within_days'] * 86400 >= $p_from)
			{
				$deposit = $amount + $tax;
				$deposit_p = 100;
			} else {
				$deposit = (($amount + $tax) * $listing_arr['o_deposit_payment']) / 100;
				$deposit_p = $listing_arr['o_deposit_payment'];
			}
			$deposit += $security;
			$total = $amount + $tax;
		}
		if ((float) $amount > 0)
		{
			$amount_f = pjUtil::formatCurrencySign(number_format($amount, 2), $this->option_arr['o_currency']);
			$security_f = pjUtil::formatCurrencySign(number_format($security, 2), $this->option_arr['o_currency']);
			$deposit_f = pjUtil::formatCurrencySign(number_format($deposit, 2), $this->option_arr['o_currency']);
			$tax_f = pjUtil::formatCurrencySign(number_format($tax, 2), $this->option_arr['o_currency']);
			$total_f = pjUtil::formatCurrencySign(number_format($total, 2), $this->option_arr['o_currency']);
		} else {
			$amount_f = __('front_index_na', true);
			$security_f = $deposit_f = $tax_f = $deposit_p = $total_f = pjUtil::formatCurrencySign(0, $this->option_arr['o_currency']);
		}
		return compact('amount', 'deposit', 'security', 'tax', 'total', 'amount_f', 'deposit_f', 'security_f', 'tax_f', 'deposit_p', 'total_f');
	}
	public function pjActionConfirmSend($option_arr, $booking_arr, $listing_arr, $type)
	{
		if (!in_array($type, array('confirm', 'payment', 'cancel')))
		{
			return false;
		}
	
		$Email = new pjEmail();
		if ($option_arr['o_send_email'] == 'smtp')
		{
			$Email
			->setTransport('smtp')
			->setSmtpHost($option_arr['o_smtp_host'])
			->setSmtpPort($option_arr['o_smtp_port'])
			->setSmtpUser($option_arr['o_smtp_user'])
			->setSmtpPass($option_arr['o_smtp_pass'])
			->setSender($option_arr['o_smtp_user'])
			;
		}
		$tokens = pjAppController::getEmailTokens($booking_arr, $listing_arr, $option_arr);
		$from_email = $this->getFromEmail($option_arr);
		switch ($type)
		{
			case 'confirm':
				if (!isset($listing_arr['confirm_subject']) || !isset($listing_arr['confirm_tokens']) ||
				empty($listing_arr['confirm_subject']) || empty($listing_arr['confirm_tokens']))
				{
					return false;
				}
				$subject = str_replace($tokens['search'], $tokens['replace'], $listing_arr['confirm_subject']);
				$message = str_replace($tokens['search'], $tokens['replace'], $listing_arr['confirm_tokens']);
	
				$Email
				->setContentType('text/html')
				->setTo($booking_arr['email'])
				->setFrom($from_email)
				->setSubject($subject)
				->send($message);
				break;
			case 'payment':
				if (!isset($listing_arr['payment_subject']) || !isset($listing_arr['payment_tokens']) ||
				empty($listing_arr['payment_subject']) || empty($listing_arr['payment_tokens']))
				{
					return false;
				}
				$subject = str_replace($tokens['search'], $tokens['replace'], $listing_arr['payment_subject']);
				$message = str_replace($tokens['search'], $tokens['replace'], $listing_arr['payment_tokens']);
	
				$Email
				->setContentType('text/html')
				->setTo($booking_arr['email'])
				->setFrom($from_email)
				->setSubject($subject)
				->send($message);
				break;
			case 'cancel':
				if (!isset($option_arr['o_email_reservation_cancelled_subject']) || !isset($option_arr['o_email_reservation_cancelled']) ||
				empty($option_arr['o_email_reservation_cancelled_subject']) || empty($option_arr['o_email_reservation_cancelled']))
				{
					return false;
				}
				$subject = str_replace($tokens['search'], $tokens['replace'], $option_arr['o_email_reservation_cancelled_subject']);
				$message = str_replace($tokens['search'], $tokens['replace'], $option_arr['o_email_reservation_cancelled']);
				
				$Email
				->setContentType('text/html')
				->setTo($booking_arr['email'])
				->setFrom($from_email)
				->setSubject($subject)
				->send($message);
	
				break;
		}
	}
}
?>