<?php
if (!defined("ROOT_PATH"))
{
	header("HTTP/1.1 403 Forbidden");
	exit;
}
class pjFrontPublic extends pjFront
{
	public function __construct()
	{
		parent::__construct();
		
		$this->setAjax(true);
		
		$this->setLayout('pjActionEmpty');
	}
	
	public function pjActionBooking()
	{
		if ($this->isXHR() || isset($_GET['_escaped_fragment_']))
		{
			if ((int) $this->option_arr['o_accept_bookings'] === 0)
			{
				$this->set('status', 'ERR');
				$this->set('code', '104'); /*Bookings are not accepted*/
				return;
			}
			
			if (isset($_GET['booking_uuid']) && !empty($_GET['booking_uuid']))
			{
				$booking_uuid = $_GET['booking_uuid'];
			} elseif (isset($_GET['_escaped_fragment_'])) {
				preg_match('/\/Booking\/([A-Z]{2}\d{10})/', $_GET['_escaped_fragment_'], $matches);
				if (isset($matches[1]))
				{
					$booking_uuid = $matches[1];
				}
			}
			
			$booking_arr = pjBookingModel::factory()->where('t1.uuid', $booking_uuid)->findAll()->limit(1)->getData();
			if (!empty($booking_arr))
			{
				$booking_arr = $booking_arr[0];
				$this->set('status', 'OK');
				
				if ((int) $this->option_arr['o_disable_payments'] === 1)
				{
					$booking_arr['payment_method'] = 'none';
					$this->set('booking_arr', $booking_arr);
					return;
				}
				
				$this->set('booking_arr', $booking_arr);
				
				$invoice_arr = pjInvoiceModel::factory()->where('t1.order_id', $booking_uuid)->findAll()->limit(1)->getData();
				if (!empty($invoice_arr))
				{
					$invoice_arr = $invoice_arr[0];
					$this->set('invoice_arr', $invoice_arr);
					
					switch ($booking_arr['payment_method'])
					{
						case 'paypal':
							$this->set('params', array(
								'name' => 'erPaypal',
								'id' => 'erPaypal',
								'target' => '_self',
								'business' => $this->option_arr['o_paypal_address'],
								'item_name' => $booking_arr['uuid'],
								'custom' => $invoice_arr['uuid'],
								'amount' => $invoice_arr['paid_deposit'],
								'currency_code' => $invoice_arr['currency'],
								'return' => $this->option_arr['o_thankyou_page'],
								'notify_url' => PJ_INSTALL_URL . 'index.php?controller=pjFrontEnd&action=pjActionConfirmPaypal',
								'submit' => __('payment_paypal_submit', true),
								'submit_class' => 'erSelectorButton erButton erButtonOrange'
							));
							break;
						case 'authorize':
							$this->set('params', array(
								'name' => 'erAuthorize',
								'id' => 'erAuthorize',
								'target' => '_self',
								'timezone' => $this->option_arr['o_authorize_tz'],
								'transkey' => $this->option_arr['o_authorize_key'],
								'x_login' => $this->option_arr['o_authorize_mid'],
								'x_description' => $booking_arr['uuid'],
								'x_amount' => $invoice_arr['paid_deposit'],
								'x_invoice_num' => $invoice_arr['uuid'],
								'x_receipt_link_url' => $this->option_arr['o_thankyou_page'],
								'x_relay_url' => PJ_INSTALL_URL . 'index.php?controller=pjFrontEnd&action=pjActionConfirmAuthorize',
								'submit' => __('payment_authorize_submit', true),
								'submit_class' => 'erSelectorButton erButton erButtonOrange'
							));
							break;
					}
				}
			} else {
				$this->set('status', 'ERR');
				$this->set('code', '105'); /*Bookings not found*/
			}
		}
	}
	
	public function pjActionCart()
	{
		if ($this->isXHR() || isset($_GET['_escaped_fragment_']))
		{
			if (isset($_POST['er_cart']))
			{
				$_SESSION[$this->defaultForm] = array_merge($_SESSION[$this->defaultForm], $_POST);
				
				pjAppController::jsonResponse(array('status' => 'OK', 'code' => 212, 'text' => __('system_212', true)));
			} else {
				if (!$this->cart->isEmpty())
				{
					$this->set('summary', $this->getSummary());
				}
			}
			
			$this->fixDatepickers();
		}
	}
	
	public function pjActionCheckout()
	{
		if ($this->isXHR() || isset($_GET['_escaped_fragment_']))
		{
			if ((int) $this->option_arr['o_accept_bookings'] === 0)
			{
				$this->set('status', 'ERR');
				$this->set('code', '104'); /*Bookings are not accepted*/
				return;
			}
			
			if (isset($_POST['er_checkout']))
			{
				$_SESSION[$this->defaultForm] = array_merge($_SESSION[$this->defaultForm], $_POST);
				
				pjAppController::jsonResponse(array('status' => 'OK', 'code' => 211, 'text' => __('system_211', true)));
			} else {
				if (!$this->cart->isEmpty())
				{
					if (in_array($this->option_arr['o_bf_country'], array(2,3)))
					{
						$this->set('country_arr', pjCountryModel::factory()
							->select('t1.*, t2.content AS name')
							->join('pjMultiLang', "t2.model='pjCountry' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='".$this->getLocaleId()."'", 'left outer')
							->where('t1.status', 'T')
							->orderBy('`name` ASC')
							->findAll()
							->getData()
						);
					}
					
					$this->set('status', 'OK');
					$this->set('summary', $this->getSummary());
				} else {
					$this->set('status', 'ERR');
					$this->set('code', '101'); /*Empty cart*/
				}
			}
		}
	}
	
	public function pjActionItem()
	{
		if ($this->isXHR() || isset($_GET['_escaped_fragment_']))
		{
			if (isset($_GET['id']) && (int) $_GET['id'] > 0)
			{
				$id = (int) $_GET['id'];
			} elseif (isset($_GET['_escaped_fragment_'])) {
				preg_match('/\/Item\/(\d+)/', $_GET['_escaped_fragment_'], $matches);
				if (isset($matches[1]))
				{
					$id = $matches[1];
				}
			}
			
			$_arr = pjItemModel::factory()->where('t1.id', $id)->where('t1.is_active', 1)->limit(1)->findAll()->getData();
			$_arr = !empty($_arr) ? $_arr[0] : array();
			
			$result = $this->getDates();
			$date_from = $date_to = $result['first_working_date'];
			if (isset($_SESSION[$this->defaultForm], $_SESSION[$this->defaultForm]['date_from'], $_SESSION[$this->defaultForm]['date_to'])
					&& !empty($_SESSION[$this->defaultForm]['date_from'])
					&& !empty($_SESSION[$this->defaultForm]['date_to']))
			{
				$date_from = $_SESSION[$this->defaultForm]['date_from'];
				$date_to = $_SESSION[$this->defaultForm]['date_to'];
				$dt_from = $date_from . " " . $_SESSION[$this->defaultForm]['hour_from'] . ":" . $_SESSION[$this->defaultForm]['minute_from'] . ":00";
				$dt_to = $date_to . " " . $_SESSION[$this->defaultForm]['hour_to'] . ":" . $_SESSION[$this->defaultForm]['minute_to'] . ":00";
			}else{
				$date_to = date('Y-m-d', (strtotime($result['first_working_date']) + 86400));
				$dt_from = $date_from . " " . (date('H') + 1) . ":00:00";
				if($_arr['rent_by_day'] == 1)
				{
					$hour_default = date('H') + 1;
					$dt_to = $date_from . " " . (date('H') + 1) . ":00:00";
				}else{
					$dt_to = $date_from . " " . (date('H') + 2) . ":00:00";
				}
			}

			$booked_qty = sprintf(",
					(SELECT COALESCE(SUM(bi.qty), 0)
					FROM `%1\$s` AS `bi`
					INNER JOIN `%2\$s` AS `b` ON b.id = bi.booking_id
						AND b.dt_from <= '%6\$s'
						AND b.dt_to > '%5\$s'
						AND b.status = 'confirmed'
					WHERE (bi.foreign_id = t1.id AND bi.type = 'item')
					OR (bi.foreign_id IN (SELECT pi.package_id
							FROM `%3\$s` AS `pi`
							INNER JOIN `%4\$s` AS `p` ON p.id = pi.package_id
							WHERE pi.item_id = t1.id) AND bi.type = 'package')
					LIMIT 1) AS `booked_qty`",
					pjBookingItemModel::factory()->getTable(),
					pjBookingModel::factory()->getTable(),
					pjPackageItemModel::factory()->getTable(),
					pjPackageModel::factory()->getTable(),
					$dt_from, $dt_to);
			$arr = pjItemModel::factory()
				->select(sprintf("t1.*, t2.content AS `title`, t3.content AS `description`, t4.content AS `category_name`,
					(SELECT `medium_path` FROM `%1\$s` WHERE `foreign_id` = `t1`.`id` LIMIT 1) AS `pic`,
					(SELECT GROUP_CONCAT(COALESCE(`small_path`, '') ORDER BY `sort` ASC SEPARATOR '~:~') FROM `%1\$s` WHERE `foreign_id` = `t1`.`id` LIMIT 1) AS `small_path`,
					(SELECT GROUP_CONCAT(COALESCE(`medium_path`, '') ORDER BY `sort` ASC SEPARATOR '~:~') FROM `%1\$s` WHERE `foreign_id` = `t1`.`id` LIMIT 1) AS `medium_path`,
					(SELECT GROUP_CONCAT(COALESCE(`alt`, '') ORDER BY `sort` ASC SEPARATOR '~:~') FROM `%1\$s` WHERE `foreign_id` = `t1`.`id` LIMIT 1) AS `alt`,
					(SELECT MIN(cnt) FROM `%2\$s` AS `t2` WHERE `t1`.`id`=`t2`.`item_id` AND '$date_from' BETWEEN `t2`.`date_from` AND `t2`.`date_to`) AS `min_from`,
					(SELECT MIN(cnt) FROM `%2\$s` AS `t2` WHERE `t1`.`id`=`t2`.`item_id` AND '$date_to' BETWEEN `t2`.`date_from` AND `t2`.`date_to`) AS `min_to`,
					$booked_qty	
					", pjGalleryModel::factory()->getTable(), pjAvailabilityModel::factory()->getTable()))
				->join('pjMultiLang', "t2.model='pjItem' AND t2.foreign_id=t1.id AND t2.locale='".$this->getLocaleId()."' AND t2.field='title'", 'left outer')
				->join('pjMultiLang', "t3.model='pjItem' AND t3.foreign_id=t1.id AND t3.locale='".$this->getLocaleId()."' AND t3.field='description'", 'left outer')
				->join('pjMultiLang', "t4.model='pjCategory' AND t4.foreign_id=t1.category_id AND t4.locale='".$this->getLocaleId()."' AND t4.field='title'", 'left outer')
				->where('t1.id', $id)
				->where('t1.is_active', 1)
				->limit(1)
				->findAll()
				->toArray('small_path', '~:~')
				->toArray('medium_path', '~:~')
				->toArray('alt', '~:~')
				->getData();

			$arr = !empty($arr) ? $arr[0] : array();
			
			$this->set('item_arr', $arr);
			
			if ((int) $this->option_arr['o_use_category'] === 1)
			{
				$this->set('category_arr', pjCategoryModel::factory()
					->select('t1.*, t2.content AS `title`')
					->join('pjMultiLang', "t2.model='pjCategory' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='".$this->getLocaleId()."'")
					->where('t1.is_active', 1)
					->findAll()->getData()
				);
			}
			
			$this->fixDatepickers();
		}
	}
	
	public function pjActionItems()
	{
		if ($this->isXHR() || isset($_GET['_escaped_fragment_']))
		{
			if (isset($_GET['_escaped_fragment_']))
			{
				preg_match('/\/Items\/date_from:([\d\-\.\/]+)?\/hour_from:(\d+)?\/minute_from:(\d+)?\/date_to:([\d\-\.\/]+)?\/hour_to:(\d+)?\/minute_to:(\d+)?\/category:(\d+)?\/page:(\d+)?/', $_GET['_escaped_fragment_'], $matches);
				if (!empty($matches))
				{
					$date_from = $matches[1];
					$hour_from = $matches[2];
					$minute_from = $matches[3];
					$date_to = $matches[4];
					$hour_to = $matches[5];
					$minute_to = $matches[6];
					$category_id = $matches[7];
					$page = $matches[8];
				}
			} else {
				$date_from = @$_GET['date_from'];
				$hour_from = @$_GET['hour_from'];
				$minute_from = @$_GET['minute_from'];
				$date_to = @$_GET['date_to'];
				$hour_to = @$_GET['hour_to'];
				$minute_to = @$_GET['minute_to'];
				$category_id = @$_GET['category_id'];
				$page = @$_GET['page'];
			}
			
			if (!empty($date_from))
			{
				$date_from = pjUtil::formatDate($date_from, $this->option_arr['o_date_format']);
			}
			if (!empty($date_to))
			{
				$date_to = pjUtil::formatDate($date_to, $this->option_arr['o_date_format']);
			}
			
			$FORM = @$_SESSION[$this->defaultForm];
			if ($FORM['date_from'] != $date_from || $FORM['date_to'] != $date_to ||
				$FORM['hour_from'] != $hour_from || $FORM['hour_to'] != $hour_to ||
				$FORM['minute_from'] != $minute_from || $FORM['minute_to'] != $minute_to)
			{
				$this->cart->clear();
			}
			
			$_SESSION[$this->defaultForm] = array_merge(
				$_SESSION[$this->defaultForm],
				compact('date_from', 'hour_from', 'minute_from', 'date_to', 'hour_to', 'minute_to')
			);
			
			if (empty($date_from) || empty($date_to))
			{
				$this->cart->clear();
			}
			
			$pjItemModel = pjItemModel::factory()
				->join('pjMultiLang', "t2.model='pjItem' AND t2.foreign_id=t1.id AND t2.locale='".$this->getLocaleId()."' AND t2.field='title'", 'left outer')
				->join('pjMultiLang', "t3.model='pjItem' AND t3.foreign_id=t1.id AND t3.locale='".$this->getLocaleId()."' AND t3.field='description'", 'left outer')
				->where('t1.is_active', 1);
			
			if (isset($category_id) && (int) $category_id > 0)
			{
				$pjItemModel->where('t1.category_id', $category_id);
			}
			
			$page = isset($page) && (int) $page > 0 ? intval($page) : 1;
			$row_count = (isset($this->option_arr['o_items_per_page']) && (int) $this->option_arr['o_items_per_page'] > 0) ? $this->option_arr['o_items_per_page'] : 6;
			$offset = ((int) $page - 1) * $row_count;
			$count = $pjItemModel->findCount()->getData();
			$pages = ceil($count / $row_count);
			
			$unavailable_days = NULL;
			if (!empty($date_from) && !empty($date_to))
			{
				$dt_from = $date_from . " " . $hour_from . ":" . $minute_from . ":00";
				$dt_to = $date_to . " " . $hour_to . ":" . $minute_to . ":00";
				
				if (strtotime($dt_from) >= strtotime($dt_to))
				{
					$this->set('out_of_range', 1);
				}
				
				$unavailable_days = sprintf(", ABS(DATEDIFF('%2\$s', '%3\$s')) + 1 AS `necessary_days`,
					(SELECT MIN(cnt) FROM `%1\$s` AS `t2` WHERE `t1`.`id`=`t2`.`item_id` AND '$date_from' BETWEEN `t2`.`date_from` AND `t2`.`date_to`) AS `min_from`,
					(SELECT MIN(cnt) FROM `%1\$s` AS `t2` WHERE `t1`.`id`=`t2`.`item_id` AND '$date_to' BETWEEN `t2`.`date_from` AND `t2`.`date_to`) AS `min_to`",
					pjAvailabilityModel::factory()->getTable(), $date_from, $date_to);
			}
			
			$price_period = $booked_qty = NULL;
			if (isset($dt_from) && isset($dt_to))
			{
				$booked_qty = sprintf(",
					(SELECT COALESCE(SUM(bi.qty), 0)
					FROM `%1\$s` AS `bi`
					INNER JOIN `%2\$s` AS `b` ON b.id = bi.booking_id
						AND b.dt_from <= '%6\$s'
						AND b.dt_to > '%5\$s'
						AND b.status = 'confirmed'
					WHERE (bi.foreign_id = t1.id AND bi.type = 'item')
					OR (bi.foreign_id IN (SELECT pi.package_id
							FROM `%3\$s` AS `pi`
							INNER JOIN `%4\$s` AS `p` ON p.id = pi.package_id
							WHERE pi.item_id = t1.id) AND bi.type = 'package')
					LIMIT 1) AS `booked_qty`",
					pjBookingItemModel::factory()->getTable(),
					pjBookingModel::factory()->getTable(),
					pjPackageItemModel::factory()->getTable(),
					pjPackageModel::factory()->getTable(),
					$dt_from, $dt_to);
			} else {
				$price_period = sprintf(",
					(SELECT MIN(`price`) FROM `%1\$s`
						WHERE `foreign_id` = `t1`.`id`
						AND `type` = 'item'
						LIMIT 1) AS `price`,
					(SELECT `period` FROM `%1\$s`
						WHERE `foreign_id` = `t1`.`id`
						AND `type` = 'item'
						GROUP BY `period`
						HAVING MIN(`price`)
						LIMIT 1) AS `period`
					",
					pjPriceModel::factory()->getTable()
				);
			}
			
			$item_arr = $pjItemModel
				->select(sprintf("t1.*, t2.content AS `title`, t3.content AS `description`,
					(SELECT `medium_path` FROM `%1\$s`
						WHERE `foreign_id` = `t1`.`id`
						ORDER BY ISNULL(`sort`), `sort` ASC, `id` ASC
						LIMIT 1) AS `pic`,
					(SELECT `small_path` FROM `%1\$s`
						WHERE `foreign_id` = `t1`.`id`
						ORDER BY ISNULL(`sort`), `sort` ASC, `id` ASC
						LIMIT 1) AS `small_pic`,
					(SELECT `content`
						FROM `%5\$s`
						WHERE `model` = 'pjCategory'
						AND `foreign_id` = `t1`.`category_id`
						AND `field` = 'title'
						AND `locale` = '%6\$u'
						LIMIT 1) AS `category_name`
					%2\$s %3\$s %4\$s",
					pjGalleryModel::factory()->getTable(),
					$price_period, $booked_qty, $unavailable_days,
					pjMultiLangModel::factory()->getTable(), $this->getLocaleId()
				))
				->index("FORCE KEY (`is_active`)")
				->orderBy('`title` ASC')
				->limit($row_count, $offset)
				->findAll()
				->getData();
			
			if (isset($dt_from) && isset($dt_to))
			{
				foreach ($item_arr as $k => $item)
				{
					$item_arr[$k]['total_price'] = $this->getPrice($item['id'], 'item', $dt_from, $dt_to);
				}
			}
			
			$haveDateOffInRange = false;
			if (!empty($date_from) && !empty($date_to))
			{
				$haveDateOffInRange = $this->getDateOffInRange($date_from, $date_to);
			}
			$this->set('haveDateOffInRange', $haveDateOffInRange);
				
			$this
				->set('item_arr', $item_arr)
				->set('paginator', compact('pages', 'page'));
			
			if ((int) $this->option_arr['o_use_category'] === 1)
			{
				$this->set('category_arr', pjCategoryModel::factory()
					->select('t1.*, t2.content AS `title`')
					->join('pjMultiLang', "t2.model='pjCategory' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='".$this->getLocaleId()."'")
					->where('t1.is_active', 1)
					->findAll()->getData()
				);
			}
			
			$this->fixDatepickers();
		}
	}
	
	public function pjActionPackage()
	{
		if ($this->isXHR() || isset($_GET['_escaped_fragment_']))
		{
			if (isset($_GET['id']) && (int) $_GET['id'] > 0)
			{
				$id = (int) $_GET['id'];
			} elseif (isset($_GET['_escaped_fragment_'])) {
				preg_match('/\/Package\/(\d+)/', $_GET['_escaped_fragment_'], $matches);
				if (isset($matches[1]))
				{
					$id = $matches[1];
				}
			}
			
			$arr = pjPackageModel::factory()
				->select(sprintf("t1.*, t2.content AS `title`, t3.content AS `description`,
					(SELECT GROUP_CONCAT(`item_id`) FROM `%1\$s` WHERE `package_id` = `t1`.`id` LIMIT 1) AS `item_ids`,
					(SELECT MIN(`cnt`) FROM `%2\$s` WHERE `id` IN (SELECT `item_id` FROM `%1\$s` WHERE `package_id` = `t1`.`id`)) AS `cnt`
					", pjPackageItemModel::factory()->getTable(), pjItemModel::factory()->getTable()
					))
				->join('pjMultiLang', "t2.model='pjPackage' AND t2.foreign_id=t1.id AND t2.locale='".$this->getLocaleId()."' AND t2.field='title'", 'left outer')
				->join('pjMultiLang', "t3.model='pjPackage' AND t3.foreign_id=t1.id AND t3.locale='".$this->getLocaleId()."' AND t3.field='description'", 'left outer')
				->where('t1.is_active', 1)
				->find($id)
				->toArray('item_ids', ',')
				->getData();
			
			$pg_arr = pjPackageGalleryModel::factory()->where('package_id', $id)->findAll()->getDataPair(null, 'gallery_id');
			
			if (!empty($arr) )
			{
				$gallery_arr = $item_arr = array();
				if (isset($arr['item_ids']) && !empty($arr['item_ids']))
				{
					$pjGalleryModel = pjGalleryModel::factory();
					if(!empty($pg_arr))
					{
						$pjGalleryModel->whereIn('t1.id', $pg_arr);
						$gallery_arr = $pjGalleryModel
							->whereIn('t1.foreign_id', $arr['item_ids'])
							->findAll()
							->getData();
					}
				}
				$arr['gallery_arr'] = $gallery_arr;
			}
			$this->set('package_arr', $arr);
			
			$this->fixDatepickers();
		}
	}
	
	public function pjActionPackages()
	{
		if ($this->isXHR() || isset($_GET['_escaped_fragment_']))
		{
			if (isset($_GET['_escaped_fragment_']))
			{
				preg_match('/\/Packages\/date_from:([\d\-\.\/]+)?\/hour_from:(\d+)?\/minute_from:(\d+)?\/date_to:([\d\-\.\/]+)?\/hour_to:(\d+)?\/minute_to:(\d+)?\/page:(\d+)?/', $_GET['_escaped_fragment_'], $matches);
				if (!empty($matches))
				{
					$date_from = $matches[1];
					$hour_from = $matches[2];
					$minute_from = $matches[3];
					$date_to = $matches[4];
					$hour_to = $matches[5];
					$minute_to = $matches[6];
					$page = $matches[7];
				}
			} else {
				$date_from = @$_GET['date_from'];
				$hour_from = @$_GET['hour_from'];
				$minute_from = @$_GET['minute_from'];
				$date_to = @$_GET['date_to'];
				$hour_to = @$_GET['hour_to'];
				$minute_to = @$_GET['minute_to'];
				$page = @$_GET['page'];
			}
			
			if (!empty($date_from))
			{
				$date_from = pjUtil::formatDate($date_from, $this->option_arr['o_date_format']);
			}
			if (!empty($date_to))
			{
				$date_to = pjUtil::formatDate($date_to, $this->option_arr['o_date_format']);
			}
			
			$FORM = @$_SESSION[$this->defaultForm];
			if ($FORM['date_from'] != $date_from || $FORM['date_to'] != $date_to ||
					$FORM['hour_from'] != $hour_from || $FORM['hour_to'] != $hour_to ||
					$FORM['minute_from'] != $minute_from || $FORM['minute_to'] != $minute_to)
			{
				$this->cart->clear();
			}
			$_SESSION[$this->defaultForm] = array_merge(
					$_SESSION[$this->defaultForm],
					compact('date_from', 'hour_from', 'minute_from', 'date_to', 'hour_to', 'minute_to')
			);
			
			$unavailable_days = NULL;
			if (!empty($date_from) && !empty($date_to))
			{
				$dt_from = $date_from . " " . $hour_from . ":" . $minute_from . ":00";
				$dt_to = $date_to . " " . $hour_to . ":" . $minute_to . ":00";
				
				if (strtotime($dt_from) >= strtotime($dt_to))
				{
					$this->set('out_of_range', 1);
				}
				
				$unavailable_days = sprintf(", ABS(DATEDIFF('%2\$s', '%3\$s')) + 1 AS `necessary_days`,
					(SELECT MIN(cnt) FROM `%1\$s` AS `t2` WHERE `t2`.`item_id` IN (SELECT `item_id` FROM `%4\$s` WHERE `package_id` = `t1`.`id`) AND '$date_from' BETWEEN `t2`.`date_from` AND `t2`.`date_to`) AS `min_from`,
					(SELECT MIN(cnt) FROM `%1\$s` AS `t2` WHERE `t2`.`item_id` IN (SELECT `item_id` FROM `%4\$s` WHERE `package_id` = `t1`.`id`) AND '$date_to' BETWEEN `t2`.`date_from` AND `t2`.`date_to`) AS `min_to`",
					pjAvailabilityModel::factory()->getTable(), $date_from, $date_to, pjPackageItemModel::factory()->getTable());
			}
			
			$price_period = $booked_qty = NULL;
			if (isset($dt_from) && isset($dt_to))
			{
				$booked_qty = sprintf(",
					(SELECT MIN(`cnt`)
						FROM `%3\$s`
						WHERE `id` IN (SELECT `item_id` FROM `%4\$s` WHERE `package_id` = `t1`.`id`)
						LIMIT 1) AS `cnt`,
					(SELECT COALESCE(SUM(bi.qty), 0)
						FROM `%1\$s` AS `bi`
						INNER JOIN `%2\$s` AS `b` ON b.id = bi.booking_id AND b.dt_from <= '%6\$s' AND b.dt_to > '%5\$s' AND b.status = 'confirmed'
						WHERE (bi.foreign_id = t1.id AND bi.type = 'package')
						OR (bi.foreign_id IN (SELECT `item_id` FROM `%4\$s` WHERE `package_id` = t1.id) AND bi.type = 'item')
						LIMIT 1) AS `booked_qty`",
					pjBookingItemModel::factory()->getTable(),
					pjBookingModel::factory()->getTable(),
					pjItemModel::factory()->getTable(),
					pjPackageItemModel::factory()->getTable(),
					$dt_from, $dt_to);
			} else {
				$price_period = sprintf(",
					(SELECT MIN(`price`) FROM `%1\$s`
						WHERE `foreign_id` = `t1`.`id`
						AND `type` = 'package'
						LIMIT 1) AS `price`,
					(SELECT `period` FROM `%1\$s`
						WHERE `foreign_id` = `t1`.`id`
						AND `type` = 'package'
						GROUP BY `period`
						HAVING MIN(`price`)
						LIMIT 1) AS `period`
					",
					pjPriceModel::factory()->getTable()
				);
			}
			
			if (!empty($date_from) && !empty($date_to))
			{
				$_SESSION[$this->defaultForm] = array_merge(
					$_SESSION[$this->defaultForm],
					compact('date_from', 'hour_from', 'minute_from', 'date_to', 'hour_to', 'minute_to')
				);
			}
			
			$pjPackageModel = pjPackageModel::factory()
				->join('pjMultiLang', "t2.model='pjPackage' AND t2.foreign_id=t1.id AND t2.locale='".$this->getLocaleId()."' AND t2.field='title'", 'left outer')
				->where('t1.is_active', 1);
			
			$count = $pjPackageModel->findCount()->getData();
			$page = isset($page) && (int) $page > 0 ? intval($page) : 1;
			$row_count = (isset($this->option_arr['o_items_per_page']) && (int) $this->option_arr['o_items_per_page'] > 0) ? $this->option_arr['o_items_per_page'] : 6;
			$offset = ((int) $page - 1) * $row_count;
			$pages = ceil($count / $row_count);
			
			if($page > $pages)
			{
				$page = 1;
				$_GET['page'] = 1;
				$row_count = (isset($this->option_arr['o_items_per_page']) && (int) $this->option_arr['o_items_per_page'] > 0) ? $this->option_arr['o_items_per_page'] : 6;
				$offset = ((int) $page - 1) * $row_count;
				$pages = ceil($count / $row_count);
			}
			
			$package_arr = $pjPackageModel
				->select(sprintf("t1.*, t2.content AS `title`,
					(SELECT GROUP_CONCAT(`item_id`) FROM `%2\$s` WHERE `package_id` = `t1`.`id` LIMIT 1) AS `items`,
					(SELECT GROUP_CONCAT(`content` SEPARATOR '~:~') FROM `%3\$s`
						WHERE `model` = 'pjItem'
						AND `foreign_id` IN (SELECT `item_id` FROM `%2\$s` WHERE `package_id` = `t1`.`id`)
						AND `field` = 'title'
						AND `locale` = '%4\$u'
						LIMIT 1) AS `titles`,
					(SELECT `medium_path` FROM `%1\$s`
						WHERE `id` IN (SELECT `gallery_id` FROM `%8\$s` AS TPG WHERE TPG.`package_id` = `t1`.`id`)
						AND `medium_path` IS NOT NULL
						ORDER BY ISNULL(`sort`), `sort` ASC, `id` ASC
						LIMIT 1) AS `pic`
					%5\$s %6\$s %7\$s",
					pjGalleryModel::factory()->getTable(), pjPackageItemModel::factory()->getTable(),
					pjMultiLangModel::factory()->getTable(), $this->getLocaleId(),
					$price_period, $booked_qty, $unavailable_days, pjPackageGalleryModel::factory()->getTable()
				))
				->index("FORCE KEY (`is_active`)")
				->orderBy('`title` ASC')
				->limit($row_count, $offset)
				->findAll()
				->toArray('titles', '~:~')
				->getData();
			
			if (isset($dt_from) && isset($dt_to))
			{
				foreach ($package_arr as $k => $package)
				{
					$package_arr[$k]['total_price'] = $this->getPrice($package['id'], 'package', $dt_from, $dt_to);
				}
			}
			
			$haveDateOffInRange = false;
			if (!empty($date_from) && !empty($date_to))
			{
				$haveDateOffInRange = $this->getDateOffInRange($date_from, $date_to);
			}
			$this->set('haveDateOffInRange', $haveDateOffInRange);
			
			$this
				->set('package_arr', $package_arr)
				->set('paginator', compact('pages', 'page'));
				
			$this->fixDatepickers();
		}
	}
	
	public function pjActionPreview()
	{
		if ($this->isXHR() || isset($_GET['_escaped_fragment_']))
		{
			if ((int) $this->option_arr['o_accept_bookings'] === 0)
			{
				$this->set('status', 'ERR');
				$this->set('code', '104'); /*Bookings are not accepted*/
				return;
			}
			
			if (!$this->cart->isEmpty())
			{
				if (!isset($_SESSION[$this->defaultForm]) || empty($_SESSION[$this->defaultForm]))
				{
					$this->set('status', 'ERR');
					$this->set('code', '102'); /*Checkout form not filled*/
				} else {
					if (in_array($this->option_arr['o_bf_country'], array(2,3)) && (int) @$_SESSION[$this->defaultForm]['c_country_id'] > 0)
					{
						$this->set('country_arr', pjCountryModel::factory()
							->select('t1.*, t2.content AS name')
							->join('pjMultiLang', "t2.model='pjCountry' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='".$this->getLocaleId()."'", 'left outer')
							->find($_SESSION[$this->defaultForm]['c_country_id'])
							->getData()
						);
					}
					$this->set('status', 'OK');
					$this->set('summary', $this->getSummary());
				}
			} else {
				$this->set('status', 'ERR');
				$this->set('code', '101'); /*Empty cart*/
			}
		}
	}
	
	public function pjActionRouter()
	{
		$this->setAjax(false);

		if (isset($_GET['_escaped_fragment_']))
		{
			$templates = array('Booking', 'Cart', 'Checkout', 'Preview', 'Item', 'Items', 'Package', 'Packages');
			preg_match('/^\/(\w+).*/', $_GET['_escaped_fragment_'], $m);
			if (isset($m[1]) && in_array($m[1], $templates))
			{
				$template = 'pjAction'.$m[1];
			
				if (method_exists($this, $template))
				{
					$this->$template();
				}
				$this->setTemplate('pjFrontPublic', $template);
			}
		}
	}
}
?>