<?php
if (!defined("ROOT_PATH"))
{
	header("HTTP/1.1 403 Forbidden");
	exit;
}
class pjAdminBookings extends pjAdmin
{
	private function pjActionCheck($uuid, $id=NULL)
	{
		$pjBookingModel = pjBookingModel::factory();
		if (!is_null($id))
		{
			$pjBookingModel->where('t1.id!=', $id);
		}
		if (0 == $pjBookingModel->where('t1.uuid', $uuid)->findCount()->getData())
		{
			return TRUE;
		}
		
		return FALSE;
	}
	
	public function pjActionCheckUuid()
	{
		$this->setAjax(true);
		
		if ($this->isXHR())
		{
			if (isset($_GET['uuid']) && pjValidation::pjActionNotEmpty($_GET['uuid']))
			{
				if (isset($_GET['id']) && (int) $_GET['id'] > 0)
				{
					echo ($this->pjActionCheck($_GET['uuid'], $_GET['id']) === TRUE) ? 'true' : 'false';
					exit;
				} else {
					echo ($this->pjActionCheck($_GET['uuid']) === TRUE) ? 'true' : 'false';
					exit;
				}
			}
			die('false');
		}
		exit;
	}
	
	public function pjActionCreate()
	{
		$this->checkLogin();
		
		if ($this->isAdmin())
		{
			if (isset($_POST['booking_create']))
			{
				pjAppController::validateCsrfToken();
				if (!$this->pjActionCheck($_POST['uuid']))
				{
					pjUtil::redirect(PJ_INSTALL_URL . "index.php?controller=pjAdminBookings&action=pjActionIndex&err=ABK09");
				}
				$data = array();
				$data['calendar_id'] = $this->getForeignId();
				$data['locale_id'] = $this->getLocaleId();
				$data['ip'] = $_SERVER['REMOTE_ADDR'];
				$data['dt_from'] = pjUtil::formatDate($_POST['date_from'], $this->option_arr['o_date_format']) . " " . $_POST['hour_from'] . ":" . $_POST['minute_from'] . ":00";
				$data['dt_to'] = pjUtil::formatDate($_POST['date_to'], $this->option_arr['o_date_format']) . " " . $_POST['hour_to'] . ":" . $_POST['minute_to'] . ":00";
				if ($_POST['payment_method'] != "creditcard")
				{
					$data['cc_type'] = ':NULL';
					$data['cc_num'] = ':NULL';
					$data['cc_code'] = ':NULL';
					$data['cc_exp_year'] = ':NULL';
					$data['cc_exp_month'] = ':NULL';
				}
				$id = pjBookingModel::factory(array_merge($_POST, $data))->insert()->getInsertId();
				if ($id !== false && (int) $id > 0)
				{
					if (isset($_SESSION[$this->adminBooking]) && isset($_SESSION[$this->adminBooking][$_POST['hash']]) && !empty($_SESSION[$this->adminBooking][$_POST['hash']]))
					{
						$pjBookingItemModel = pjBookingItemModel::factory();
						$pjBookingItemModel->setBatchFields(array('booking_id', 'foreign_id', 'type', 'qty', 'unit_price'));
						foreach ($_SESSION[$this->adminBooking][$_POST['hash']] as $key => $item)
						{
							$pjBookingItemModel->addBatchRow(array(
								$id, $item['foreign_id'], $item['type'], $item['qty'], $item['unit_price']
							));
						}
						$pjBookingItemModel->insertBatch();
						
						$_SESSION[$this->adminBooking] = NULL;
						unset($_SESSION[$this->adminBooking]);
					}
					$err = 'ABK03';
				} else {
					$err = 'ABK04';
				}
				pjUtil::redirect($_SERVER['PHP_SELF'] . "?controller=pjAdminBookings&action=pjActionIndex&err=$err");
			} else {
				$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
					->appendCss('chosen.css', PJ_THIRD_PARTY_PATH . 'chosen/')
					->appendJs('chosen.jquery.min.js', PJ_THIRD_PARTY_PATH . 'chosen/')
					->appendJs('jquery.validate.min.js', PJ_THIRD_PARTY_PATH . 'validate/')
					->appendJs('pjAdminBookings.js');
			}
		} else {
			$this->set('status', 2);
		}
	}
	
	public function pjActionDeleteBooking()
	{
		$this->setAjax(true);
	
		if ($this->isXHR() && $this->isLoged())
		{
			if (isset($_GET['id']) && (int) $_GET['id'] > 0 && pjBookingModel::factory()->set('id', $_GET['id'])->erase()->getAffectedRows() == 1)
			{
				pjBookingItemModel::factory()->where('booking_id', $_GET['id'])->eraseAll();
				pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => ''));
			}
			pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => ''));
		}
		exit;
	}
	
	public function pjActionDeleteBookingBulk()
	{
		$this->setAjax(true);
	
		if ($this->isXHR() && $this->isLoged())
		{
			if (isset($_POST['record']) && !empty($_POST['record']))
			{
				pjBookingModel::factory()->whereIn('id', $_POST['record'])->eraseAll();
				pjBookingItemModel::factory()->whereIn('booking_id', $_POST['record'])->eraseAll();
				pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => ''));
			}
			pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => ''));
		}
		exit;
	}
	
	public function pjActionGetBooking()
	{
		$this->setAjax(true);
	
		if ($this->isXHR() && $this->isLoged())
		{
			$pjBookingModel = pjBookingModel::factory()->where('t1.id > 0');
			$pjBookingItemModel = pjBookingItemModel::factory();
				
			if (isset($_GET['q']) && !empty($_GET['q']))
			{
				$q = $pjBookingModel->escapeString($_GET['q']);
				$q = str_replace(array('%', '_'), array('\%', '\_'), trim($q));
				$pjBookingModel->where(sprintf("(t1.uuid LIKE '%1\$s' OR t1.c_email LIKE '%1\$s' OR t1.c_name LIKE '%1\$s')", "%$q%"));
			}

			if (isset($_GET['status']) && !empty($_GET['status']) && in_array($_GET['status'], array('confirmed', 'pending', 'cancelled', 'ongoing')))
			{
				if($_GET['status'] == 'ongoing')
				{
					$pjBookingModel->where("CURDATE() BETWEEN DATE(t1.dt_from) AND DATE(t1.dt_to)");
				}else{
					$pjBookingModel->where('t1.status', $_GET['status']);
				}
			}
				
			if (isset($_GET['item_id']) && (int) $_GET['item_id'] > 0)
			{
				$pjBookingModel->where(sprintf("t1.id IN (
					SELECT `booking_id`
					FROM `%s`
					WHERE `foreign_id` = '%u'
					AND `type` = 'item'
				)", $pjBookingItemModel->getTable(), (int) $_GET['item_id']));
			}

			if (isset($_GET['package_id']) && (int) $_GET['package_id'] > 0)
			{
				$pjBookingModel->where(sprintf("t1.id IN (
					SELECT `booking_id`
					FROM `%s`
					WHERE `foreign_id` = '%u'
					AND `type` = 'package'
				)", $pjBookingItemModel->getTable(), (int) $_GET['package_id']));
			}
			
			if (isset($_GET['category_id']) && (int) $_GET['category_id'] > 0)
			{
				$pjBookingModel->where(sprintf("t1.id IN (
					SELECT bi.booking_id
					FROM `%s` AS `bi`
					INNER JOIN `%s` AS `i` ON i.id = bi.foreign_id AND i.category_id = '%u'
					WHERE bi.type = 'item'
				)", $pjBookingItemModel->getTable(), pjItemModel::factory()->getTable(), (int) $_GET['category_id']));
			}
			
			if (isset($_GET['date_from']) && isset($_GET['date_to']) && !empty($_GET['date_from']) && !empty($_GET['date_to']))
			{
				$date_from = pjUtil::formatDate($_GET['date_from'], $this->option_arr['o_date_format']);
				$date_to = pjUtil::formatDate($_GET['date_to'], $this->option_arr['o_date_format']);
				$pjBookingModel->where('((DATE(t1.dt_from) BETWEEN "'.$date_from.'" AND "'.$date_to.'") OR ("'.$date_from.'" BETWEEN DATE(t1.dt_from) AND DATE(t1.dt_to))  OR ("'.$date_to.'" BETWEEN DATE(t1.dt_from) AND DATE(t1.dt_to)))');
			} else {
				if (isset($_GET['date_from']) && !empty($_GET['date_from']))
				{
					$date_from = pjUtil::formatDate($_GET['date_from'], $this->option_arr['o_date_format']);
					$pjBookingModel->where(sprintf("DATE(t1.dt_from) >= '%s'", $date_from));
				}
				if (isset($_GET['date_to']) && !empty($_GET['date_to']))
				{
					$date_to = pjUtil::formatDate($_GET['date_to'], $this->option_arr['o_date_format']);
					$pjBookingModel->where(sprintf("DATE(t1.dt_to) <= '%s'", $date_to));
				}
			}
			
			$column = 'id';
			$direction = 'DESC';
			$allowed_columns = array('t1.id', 'id', 'created', 't1.status', 'c_name', 'item_title', 'total', 'date_from', 'date_to');
			if (isset($_GET['direction']) && isset($_GET['column']) && in_array(strtoupper($_GET['direction']), array('ASC', 'DESC')) && in_array($_GET['column'], $allowed_columns))
			{
				$column = $_GET['column'];
				$direction = strtoupper($_GET['direction']);
			}

			$total = $pjBookingModel->findCount()->getData();
			$rowCount = isset($_GET['rowCount']) && (int) $_GET['rowCount'] > 0 ? (int) $_GET['rowCount'] : 10;
			$pages = ceil($total / $rowCount);
			$page = isset($_GET['page']) && (int) $_GET['page'] > 0 ? intval($_GET['page']) : 1;
			$offset = ((int) $page - 1) * $rowCount;
			if ($page > $pages)
			{
				$page = $pages;
			}

			$data = $pjBookingModel
				->select(sprintf("t1.*,
					(SELECT GROUP_CONCAT(CONCAT_WS('~.~', bi.foreign_id, bi.type, bi.qty, m.content) SEPARATOR '~:~')
						FROM `%1\$s` AS `bi`
						LEFT JOIN `%2\$s` AS `m` ON m.model=IF(bi.type='item','pjItem','pjPackage') AND m.foreign_id=bi.foreign_id AND m.field='title' AND m.locale='%3\$u'
						WHERE bi.booking_id = t1.id) AS `items`
					", pjBookingItemModel::factory()->getTable(), pjMultiLangModel::factory()->getTable(), $this->getLocaleId()))
				->orderBy("$column $direction")->limit($rowCount, $offset)
				->findAll()
				->toArray('items', '~:~')
				->getData();

			pjAppController::jsonResponse(compact('data', 'total', 'pages', 'page', 'rowCount', 'column', 'direction'));
		}
		exit;
	}
	
	public function pjActionGetPrice()
	{
		$this->setAjax(true);
		
		if ($this->isXHR() && $this->isLoged())
		{
			$price = $security = $deposit = $tax = $delivery = $collection = $total = 0;
			
			if (isset($_POST['id']) && (int) $_POST['id'] > 0)
			{
				$pjBookingItemModel = pjBookingItemModel::factory();
				$bi_arr = $pjBookingItemModel->where('t1.booking_id', $_POST['id'])->findAll()->getData();
				foreach ($bi_arr as $item)
				{
					$dt_from = pjUtil::formatDate($_POST['date_from'], $this->option_arr['o_date_format']) . " " . $_POST['hour_from'] . ":" . $_POST['minute_from'] . ":00";
					$dt_to = pjUtil::formatDate($_POST['date_to'], $this->option_arr['o_date_format']) . " " . $_POST['hour_to'] . ":" . $_POST['minute_to'] . ":00";
					$unit_price = $this->getPrice($item['foreign_id'], $item['type'], $dt_from, $dt_to);
					$pjBookingItemModel->reset()->where('id', $item['id'])->limit(1)->modifyAll(array('unit_price' => $unit_price));
					$price += $item['qty'] * $unit_price;
				}
			} elseif (isset($_POST['hash']) && !empty($_POST['hash']) && isset($_SESSION[$this->adminBooking]) && isset($_SESSION[$this->adminBooking][$_POST['hash']])) {
				foreach ($_SESSION[$this->adminBooking][$_POST['hash']] as $key => $item)
				{
					$dt_from = pjUtil::formatDate($_POST['date_from'], $this->option_arr['o_date_format']) . " " . $_POST['hour_from'] . ":" . $_POST['minute_from'] . ":00";
					$dt_to = pjUtil::formatDate($_POST['date_to'], $this->option_arr['o_date_format']) . " " . $_POST['hour_to'] . ":" . $_POST['minute_to'] . ":00";
					$unit_price = $this->getPrice($item['foreign_id'], $item['type'], $dt_from, $dt_to);
					$price += $item['qty'] * $unit_price;
					$_SESSION[$this->adminBooking][$_POST['hash']][$key]['unit_price'] = $unit_price;
				}
			}
			
			if ((float) $this->option_arr['o_tax'] > 0)
			{
				$tax = ($price * (float) $this->option_arr['o_tax']) / 100;
			}
			
			if ((float) $this->option_arr['o_security'] > 0)
			{
				$security = (float) $this->option_arr['o_security'];
			}
			
			if (isset($_POST['forth']) && $_POST['forth'] == 'delivery')
			{
				$delivery = (float) $this->option_arr['o_delivery'];
			}
			if (isset($_POST['back']) && $_POST['back'] == 'collection')
			{
				$collection = (float) $this->option_arr['o_collection'];
			}
			$total = $price + $tax + $delivery + $collection;
			
			switch ($this->option_arr['o_deposit_type'])
			{
				case 'percent':
					$deposit = ($total * (float) $this->option_arr['o_deposit']) / 100;
					break;
				case 'amount':
					$deposit = (float) $this->option_arr['o_deposit'];
					break;
			}
			$deposit += $security;
			
			$data = compact('price', 'security', 'deposit', 'tax', 'total', 'delivery', 'collection');
			$data = array_map('floatval', $data);
			
			pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => '', 'data' => $data));
		}
		exit;
	}
	
	public function pjActionIndex()
	{
		$this->checkLogin();
		
		if ($this->isAdmin())
		{
			$this->set('item_arr', pjItemModel::factory()
				->select('t1.*, t2.content AS `title`')
				->join('pjMultiLang', sprintf("t2.model='pjItem' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
				->orderBy('`title` ASC')
				->findAll()
				->getData()
			);
			
			$this->set('package_arr', pjPackageModel::factory()
				->select('t1.*, t2.content AS `title`')
				->join('pjMultiLang', sprintf("t2.model='pjPackage' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
				->orderBy('`title` ASC')
				->findAll()
				->getData()
			);
			
			$this->set('category_arr', pjCategoryModel::factory()
				->select('t1.*, t2.content AS `title`')
				->join('pjMultiLang', sprintf("t2.model='pjCategory' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
				->orderBy('`title` ASC')
				->findAll()
				->getData()
			);
			$this->appendJs('jquery.datagrid.js', PJ_FRAMEWORK_LIBS_PATH . 'pj/js/');
			$this->appendJs('pjAdminBookings.js');
			$this->appendJs('index.php?controller=pjAdmin&action=pjActionMessages', PJ_INSTALL_URL, true);
		} else {
			$this->set('status', 2);
		}
	}
	
	public function pjActionSaveBooking()
	{
		$this->setAjax(true);
	
		if ($this->isXHR() && $this->isLoged())
		{
			$pjBookingModel = pjBookingModel::factory();
			if (!in_array($_POST['column'], $pjBookingModel->getI18n()))
			{
				$pjBookingModel->set('id', $_GET['id'])->modify(array($_POST['column'] => $_POST['value']));
			} else {
				pjMultiLangModel::factory()->updateMultiLang(array($this->getLocaleId() => array($_POST['column'] => $_POST['value'])), $_GET['id'], 'pjBooking');
			}
		}
		exit;
	}
	
	public function pjActionUpdate()
	{
		$this->checkLogin();
		
		if ($this->isAdmin())
		{
			if (isset($_POST['booking_update']))
			{
				pjAppController::validateCsrfToken();
				if (!$this->pjActionCheck($_POST['uuid'], $_POST['id']))
				{
					pjUtil::redirect(PJ_INSTALL_URL . "index.php?controller=pjAdminBookings&action=pjActionIndex&err=ABK09");
				}
				
				$data = array();
				$data['dt_from'] = pjUtil::formatDate($_POST['date_from'], $this->option_arr['o_date_format']) . " " . $_POST['hour_from'] . ":" . $_POST['minute_from'] . ":00";
				$data['dt_to'] = pjUtil::formatDate($_POST['date_to'], $this->option_arr['o_date_format']) . " " . $_POST['hour_to'] . ":" . $_POST['minute_to'] . ":00";
				if ($_POST['payment_method'] != "creditcard")
				{
					$data['cc_type'] = ':NULL';
					$data['cc_num'] = ':NULL';
					$data['cc_code'] = ':NULL';
					$data['cc_exp_year'] = ':NULL';
					$data['cc_exp_month'] = ':NULL';
				}
				pjBookingModel::factory()->set('id', $_POST['id'])->modify(array_merge($_POST, $data));
				pjUtil::redirect(PJ_INSTALL_URL . "index.php?controller=pjAdminBookings&action=pjActionIndex&err=ABK01");
				
			} else {
				
				$pjBookingModel = pjBookingModel::factory();
				if (isset($_REQUEST['id']) && (int) $_REQUEST['id'] > 0)
				{
					$pjBookingModel->where('t1.id', $_REQUEST['id']);
				} elseif (isset($_GET['uuid']) && !empty($_GET['uuid'])) {
					$pjBookingModel->where('t1.uuid', $_GET['uuid']);
				}
				$arr = $pjBookingModel->findAll()->getData();
				if (empty($arr) || count($arr) == 0)
				{
					pjUtil::redirect(PJ_INSTALL_URL. "index.php?controller=pjAdminBookings&action=pjActionIndex&err=ABK08");
				}
				$arr = $arr[0];
				
				$this->set('arr', $arr)
					->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')
						->orderBy('`name` ASC')
						->findAll()->getData());
				
				$this->set('bi_arr', pjBookingItemModel::factory()
					->select('t1.*, t2.content AS `title`')
					->join('pjMultiLang', sprintf("t2.model=IF(t1.type='item','pjItem','pjPackage') AND t2.foreign_id=t1.foreign_id AND t2.field='title' AND t2.locale='%u'", $arr['locale_id']), 'left outer')
					->where('t1.booking_id', $arr['id'])
					->findAll()
					->getData()
				);
				
				$this
					->appendCss('chosen.css', PJ_THIRD_PARTY_PATH . 'chosen/')
					->appendJs('chosen.jquery.min.js', PJ_THIRD_PARTY_PATH . 'chosen/')
					->appendCss('jquery-ui-timepicker-addon.css', PJ_THIRD_PARTY_PATH . 'datetimepicker/')
					->appendJs('jquery-ui-timepicker-addon.js', PJ_THIRD_PARTY_PATH . 'datetimepicker/')
					->appendJs('jquery.validate.min.js', PJ_THIRD_PARTY_PATH . 'validate/')
					->appendJs('jquery.datagrid.js', PJ_FRAMEWORK_LIBS_PATH . 'pj/js/')
					->appendJs('tinymce.min.js', PJ_THIRD_PARTY_PATH . 'tinymce/')
					->appendJs('pjAdminBookings.js')
					->appendJs('index.php?controller=pjAdmin&action=pjActionMessages', PJ_INSTALL_URL, true)
				;
			}
		} else {
			$this->set('status', 2);
		}
	}
		
	public function pjActionItemAdd()
	{
		$this->setAjax(true);
		
		if ($this->isXHR() && $this->isLoged())
		{
			$pjBookingItemModel = pjBookingItemModel::factory();
			
			if (isset($_POST['item_add']))
			{
				pjAppController::validateCsrfToken();
				if (isset($_POST['foreign_id']) && !empty($_POST['foreign_id']))
				{
					$dt_from = pjUtil::formatDate($_POST['date_from'], $this->option_arr['o_date_format']) . " " . $_POST['hour_from'] . ":" . $_POST['minute_from'] . ":00";
					$dt_to = pjUtil::formatDate($_POST['date_to'], $this->option_arr['o_date_format']) . " " . $_POST['hour_to'] . ":" . $_POST['minute_to'] . ":00";
					list($type, $foreign_id) = explode("_", $_POST['foreign_id']);
					
					if (isset($_POST['booking_id']) && (int) $_POST['booking_id'] > 0)
					{
						$bi_id = $pjBookingItemModel->reset()->setAttributes(array(
							'booking_id' => $_POST['booking_id'],
							'foreign_id' => $foreign_id,
							'type' => $type,
							'qty' => $_POST['qty'],
							'unit_price' => $this->getPrice($foreign_id, $type, $dt_from, $dt_to)
						))->insert()->getInsertId();
						
						if ($bi_id !== FALSE && (int) $bi_id > 0)
						{
							pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Item has been added.'));
						}
					} elseif (isset($_POST['hash']) && !empty($_POST['hash'])) {
						if (!isset($_SESSION[$this->adminBooking]))
						{
							$_SESSION[$this->adminBooking] = array();
						}
						if (!isset($_SESSION[$this->adminBooking][$_POST['hash']]))
						{
							$_SESSION[$this->adminBooking][$_POST['hash']] = array();
						}
						
						$arr = pjMultiLangModel::factory()
							->where('t1.model', $type == 'item' ? 'pjItem' : 'pjPackage')
							->where('t1.foreign_id', $foreign_id)
							->where('t1.field', 'title')
							->where('t1.locale', $this->getLocaleId())
							->limit(1)
							->findAll()
							->getDataIndex(0);
						$unit_price = $this->getPrice($foreign_id, $type, $dt_from, $dt_to);
						$key = $foreign_id . '~' . $type;
						$_SESSION[$this->adminBooking][$_POST['hash']][$key] = array(
							'foreign_id' => $foreign_id,
							'type' => $type,
							'qty' => $_POST['qty'],
							'unit_price' => $unit_price,
							'name' => @$arr['content']
						);
						
						pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Item has been added.'));
					}
					pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Item has not been added.'));
				}
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Item couldn\'t be empty.'));
			}
			
			$pjItemModel = pjItemModel::factory();
			$pjPackageModel = pjPackageModel::factory();
			
			if (isset($_GET['id']) && (int) $_GET['id'])
			{
				$bi_arr = $pjBookingItemModel
					->where('t1.booking_id', $_GET['id'])
					->findAll()
					->getData();
					
				$bi_items = $bi_packages = array();
				foreach ($bi_arr as $item)
				{
					switch ($item['type'])
					{
						case 'item':
							$bi_items[] = $item['foreign_id'];
							break;
						case 'package':
							$bi_packages[] = $item['foreign_id'];
							break;
					}
				}
				if (!empty($bi_items))
				{
					$pjItemModel->whereNotIn('t1.id', $bi_items);
				}
				if (!empty($bi_packages))
				{
					$pjPackageModel->whereNotIn('t1.id', $bi_packages);
				}
			}

			$date_from = pjUtil::formatDate($_GET['date_from'], $this->option_arr['o_date_format']);
			$date_to = pjUtil::formatDate($_GET['date_to'], $this->option_arr['o_date_format']);
			
			$dt_from = $date_from . " " . $_GET['hour_from'] . ":" . $_GET['minute_from'] . ":00";
			$dt_to = $date_to . " " . $_GET['hour_to'] . ":" . $_GET['minute_to'] . ":00";
			
			$items = $pjItemModel
				->select(sprintf("t1.*, t2.content AS title, 'item' AS `type`,
					(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`,
					ABS(DATEDIFF('%2\$s', '%3\$s')) + 1 AS `necessary_days`,
					(SELECT COALESCE(SUM(bi.qty), 0)
						FROM `%4\$s` AS `bi`
						INNER JOIN `%5\$s` AS `b` ON b.id = bi.booking_id
							AND b.status = 'confirmed'
							AND b.dt_from <= '%7\$s'
							AND b.dt_to > '%6\$s'
						WHERE (bi.foreign_id = t1.id AND bi.type = 'item')
						OR (bi.foreign_id IN (SELECT pi.package_id
								FROM `%8\$s` AS `pi`
								INNER JOIN `%9\$s` AS `p` ON p.id = pi.package_id
								WHERE pi.item_id = t1.id) AND bi.type = 'package')
						LIMIT 1
					) AS `booked_qty`
					",
					pjAvailabilityModel::factory()->getTable(), $date_from, $date_to,
					pjBookingItemModel::factory()->getTable(), pjBookingModel::factory()->getTable(),
					$dt_from, $dt_to,
					pjPackageItemModel::factory()->getTable(),
					pjPackageModel::factory()->getTable()
				))
				->join('pjMultiLang', "t2.model='pjItem' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='".$this->getLocaleId()."'")
				->where('t1.is_active', 1)
				->orderBy("`title` ASC")
				->findAll()
				->getData();
			
			$packages = $pjPackageModel
				->select(sprintf("t1.*, t2.content AS `title`, 'package' AS `type`,
					(SELECT MIN(cnt) FROM `%1\$s` AS `t2` WHERE `t2`.`item_id` IN (SELECT `item_id` FROM `%9\$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 `%9\$s` WHERE `package_id` = `t1`.`id`) AND '$date_to' BETWEEN `t2`.`date_from` AND `t2`.`date_to`) AS `min_to`,
					(SELECT MIN(`cnt`) FROM `%8\$s` WHERE `id` IN (SELECT `item_id` FROM `%9\$s` WHERE `package_id` = t1.id) LIMIT 1) AS `cnt`,
					ABS(DATEDIFF('%2\$s', '%3\$s')) + 1 AS `necessary_days`,
					(SELECT COALESCE(SUM(bi.qty), 0)
						FROM `%4\$s` AS `bi`
						INNER JOIN `%5\$s` AS `b` ON b.id = bi.booking_id
							AND b.status = 'confirmed'
							AND b.dt_from <= '%7\$s'
							AND b.dt_to > '%6\$s'
						WHERE (bi.foreign_id = t1.id AND bi.type = 'package')
						OR (bi.foreign_id IN (SELECT `item_id` FROM `%9\$s` WHERE `package_id` = t1.id) AND bi.type = 'item')
						LIMIT 1
					) AS `booked_qty`
					",
					pjAvailabilityModel::factory()->getTable(), $date_from, $date_to,
					pjBookingItemModel::factory()->getTable(), pjBookingModel::factory()->getTable(),
					$dt_from, $dt_to, pjItemModel::factory()->getTable(), pjPackageItemModel::factory()->getTable()
				))
				->join('pjMultiLang', "t2.model='pjPackage' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='".$this->getLocaleId()."'")
				->where('t1.is_active', 1)
				->orderBy("`title` ASC")
				->findAll()
				->getData();
			
			$this->set('item_arr', $items);
			$this->set('package_arr', $packages);
		}
	}
	
	public function pjActionItemDelete()
	{
		$this->setAjax(true);
		
		if ($this->isXHR() && $this->isLoged())
		{
			if (isset($_POST['id']) && (int) $_POST['id'] > 0)
			{
				$pjBookingItemModel = pjBookingItemModel::factory();
				$arr = $pjBookingItemModel->find($_POST['id'])->getData();
				if (empty($arr))
				{
					pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 103, 'text' => 'Item not found.'));
				}
				if (1 == $pjBookingItemModel->set('id', $_POST['id'])->erase()->getAffectedRows())
				{
					pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Item has been deleted.'));
				}
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 102, 'text' => 'Item has not been deleted.'));
			} elseif (isset($_POST['hash']) && !empty($_POST['hash']) && isset($_POST['key']) && !empty($_POST['key'])) {
				if (isset($_SESSION[$this->adminBooking]) &&
					isset($_SESSION[$this->adminBooking][$_POST['hash']]) &&
					isset($_SESSION[$this->adminBooking][$_POST['hash']][$_POST['key']])
				)
				{
					$_SESSION[$this->adminBooking][$_POST['hash']][$_POST['key']] = NULL;
					unset($_SESSION[$this->adminBooking][$_POST['hash']][$_POST['key']]);
					pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Item has been deleted.'));
				} else {
					pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 103, 'text' => 'Item not found.'));
				}
			}
			pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 101, 'text' => 'Missing parameters.'));
		}
		pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Access denied.'));
		exit;
	}

	public function pjActionItemEdit()
	{
		$this->setAjax(true);
		
		if ($this->isXHR() && $this->isLoged())
		{
			$pjBookingItemModel = pjBookingItemModel::factory();
			if (isset($_POST['item_edit']))
			{
				pjAppController::validateCsrfToken();
				$arr = $pjBookingItemModel->find($_POST['booking_item_id'])->getData();
				if (empty($arr))
				{
					pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Item not found'));
				}
				list($type, $foreign_id) = explode("_", $_POST['foreign_id']);
				
				$dt_from = pjUtil::formatDate($_POST['date_from'], $this->option_arr['o_date_format']) . " " . $_POST['hour_from'] . ":" . $_POST['minute_from'] . ":00";
				$dt_to = pjUtil::formatDate($_POST['date_to'], $this->option_arr['o_date_format']) . " " . $_POST['hour_to'] . ":" . $_POST['minute_to'] . ":00";
				
				$pjBookingItemModel->modify(array(
					'foreign_id' => $foreign_id,
					'type' => $type,
					'qty' => (int) $_POST['qty'],
					'unit_price' => $this->getPrice($foreign_id, $type, $dt_from, $dt_to),
				));
				
				pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Item has been updated'));
			}
			
			$arr = $pjBookingItemModel
				->select(sprintf("t1.*, t2.cnt AS max_qty,
					(SELECT GROUP_CONCAT(`foreign_id`) FROM `%1\$s` WHERE `booking_id` = t1.booking_id AND `type` = 'item' AND `id` != t1.id LIMIT 1) AS `items`,
					(SELECT GROUP_CONCAT(`foreign_id`) FROM `%1\$s` WHERE `booking_id` = t1.booking_id AND `type` = 'package' AND `id` != t1.id LIMIT 1) AS `packages`
				", $pjBookingItemModel->getTable()))
				->join('pjItem', "t2.id=t1.foreign_id AND t1.type='item'", 'left outer')
				->find($_GET['booking_item_id'])
				->toArray('items', ',')
				->toArray('packages', ',')
				->getData();
			
			$pjItemModel = pjItemModel::factory();
			$pjPackageModel = pjPackageModel::factory();
				
			if (!empty($arr['items']))
			{
				$pjItemModel->whereNotIn('t1.id', $arr['items']);
			}
			if (!empty($arr['packages']))
			{
				$pjPackageModel->whereNotIn('t1.id', $arr['packages']);
			}
			
			$items = $pjItemModel
				->select("t1.*, t2.content AS title, 'item' AS `type`")
				->join('pjMultiLang', "t2.model='pjItem' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='".$this->getLocaleId()."'")
				->where('t1.is_active', 1)
				->orderBy("`title` ASC")
				->findAll()
				->getData();
			
			$packages = $pjPackageModel
				->select(sprintf("t1.*, t2.content AS `title`, 'package' AS `type`,
					(SELECT MIN(`cnt`) FROM `%s` WHERE `id` IN (SELECT `item_id` FROM `%s` WHERE `package_id` = `t1`.`id`)) AS `cnt`
					", $pjItemModel->getTable(), pjPackageItemModel::factory()->getTable()))
				->join('pjMultiLang', "t2.model='pjPackage' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='".$this->getLocaleId()."'")
				->where('t1.is_active', 1)
				->orderBy("`title` ASC")
				->findAll()
				->getData();
			
			$this
				->set('arr', $arr)
				->set('item_arr', $items)
				->set('package_arr', $packages);
			
		}
	}
	
	public function pjActionItemGet()
	{
		$this->setAjax(true);
		
		if ($this->isXHR() && $this->isLoged())
		{
			if (isset($_GET['id']) && (int) $_GET['id'] > 0)
			{
				$bi_arr = pjBookingItemModel::factory()
					->select("t1.*, t2.content AS name")
					->join('pjMultiLang', "t2.model=IF(t1.type='item','pjItem','pjPackage') AND t2.foreign_id=t1.foreign_id AND t2.field='title' AND t2.locale='".$this->getLocaleId()."'")
					->join('pjBooking', 't3.id=t1.booking_id', 'inner')
					->where('t1.booking_id', $_GET['id'])->findAll()->getData();
			
			} elseif (isset($_GET['hash']) && !empty($_GET['hash'])) {
				
				$bi_arr = @$_SESSION[$this->adminBooking][$_GET['hash']];
				
			}
			$this->set('bi_arr', $bi_arr);
		}
	}
	
	public function pjActionConfirmation()
	{
		$this->setAjax(true);
	
		if ($this->isXHR())
		{
			if (isset($_POST['send_confirm']) && !empty($_POST['to']) && !empty($_POST['from']) &&
					!empty($_POST['subject']) && !empty($_POST['message']))
			{
				$Email = new pjEmail();
				$Email->setContentType('text/html');
				if ($this->option_arr['o_send_email'] == 'smtp')
				{
					$Email
					->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']);
				}
	
				$subject = $_POST['subject'];
				$message = $_POST['message'];
				if (get_magic_quotes_gpc())
				{
					$subject = stripslashes($_POST['subject']);
					$message = stripslashes($_POST['message']);
				}
	
				$r = $Email
				->setTo($_POST['to'])
				->setFrom($_POST['from'])
				->setSubject($subject)
				->send($message);
					
				if ($r)
				{
					pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Email has been sent.'));
				}
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Email failed to send.'));
			}
	
			if (isset($_GET['booking_id']) && (int) $_GET['booking_id'] > 0)
			{
				$pjBookingModel = pjBookingModel::factory();
				
				$booking_arr = $pjBookingModel
					->select('t1.*, t2.content AS country')
					->join('pjMultiLang', "t2.model='pjCountry' AND t2.foreign_id=t1.c_country_id AND t2.locale=t1.locale_id AND t2.field='name'", 'left outer')
					->find($_GET['booking_id'])
					->getData();
				$calendar_arr = pjCalendarModel::factory()
					->select(sprintf("t1.*, t2.content AS confirm_subject_client, t3.content AS confirm_tokens_client,
						(SELECT GROUP_CONCAT(`email`) FROM `%s` WHERE `role_id` = '1' AND `status` = 'T') AS `email`", pjUserModel::factory()->getTable()))
					->join('pjMultiLang', "t2.model='pjCalendar' AND t2.foreign_id=t1.id AND t2.field='confirm_subject_client' AND t2.locale='".$booking_arr['locale_id']."'", 'left outer')
					->join('pjMultiLang', "t3.model='pjCalendar' AND t3.foreign_id=t1.id AND t3.field='confirm_tokens_client' AND t3.locale='".$booking_arr['locale_id']."'", 'left outer')
					->find($booking_arr['calendar_id'])
					->toArray('email', ',')
					->getData();
				
				$option_arr = pjOptionModel::factory()->getPairs($booking_arr['calendar_id']);
				
				$tokens = pjAppController::getTokens($booking_arr, $option_arr);
				
				$subject_client = str_replace($tokens['search'], $tokens['replace'], @$calendar_arr['confirm_subject_client']);
				$message_client = pjUtil::textToHtml(str_replace($tokens['search'], $tokens['replace'], @$calendar_arr['confirm_tokens_client']));
				
				if (!empty($subject_client) && !empty($message_client))
				{
					$from = !empty($calendar_arr['email']) ? $calendar_arr['email'][0] : $booking_arr['c_email'];
					$this->set('arr', array(
							'to' => $booking_arr['c_email'],
							'from' => $from,
							'message' => $message_client,
							'subject' => $subject_client
					));
				}
			} else {
				exit;
			}
		}
	}
	
	public function pjActionSendPayment()
	{
		$this->setAjax(true);
	
		if ($this->isXHR())
		{
			if (isset($_POST['send_payment']) && !empty($_POST['to']) && !empty($_POST['from']) &&
					!empty($_POST['subject']) && !empty($_POST['message']))
			{
				$Email = new pjEmail();
				$Email->setContentType('text/html');
				if ($this->option_arr['o_send_email'] == 'smtp')
				{
					$Email
					->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']);
				}
	
				$subject = $_POST['subject'];
				$message = $_POST['message'];
				if (get_magic_quotes_gpc())
				{
					$subject = stripslashes($_POST['subject']);
					$message = stripslashes($_POST['message']);
				}
	
				$r = $Email
				->setTo($_POST['to'])
				->setFrom($_POST['from'])
				->setSubject($subject)
				->send($message);
					
				if ($r)
				{
					pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Email has been sent.'));
				}
				pjAppController::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Email failed to send.'));
			}
	
			if (isset($_GET['booking_id']) && (int) $_GET['booking_id'] > 0)
			{
				$pjBookingModel = pjBookingModel::factory();
				
				$booking_arr = $pjBookingModel
					->select('t1.*, t2.content AS country')
					->join('pjMultiLang', "t2.model='pjCountry' AND t2.foreign_id=t1.c_country_id AND t2.locale=t1.locale_id AND t2.field='name'", 'left outer')
					->find($_GET['booking_id'])
					->getData();
				$calendar_arr = pjCalendarModel::factory()
					->select(sprintf("t1.*, t2.content AS payment_subject_client, t3.content AS payment_tokens_client,
						(SELECT GROUP_CONCAT(`email`) FROM `%s` WHERE `role_id` = '1' AND `status` = 'T') AS `email`", pjUserModel::factory()->getTable()))
					->join('pjMultiLang', "t2.model='pjCalendar' AND t2.foreign_id=t1.id AND t2.field='payment_subject_client' AND t2.locale='".$booking_arr['locale_id']."'", 'left outer')
					->join('pjMultiLang', "t3.model='pjCalendar' AND t3.foreign_id=t1.id AND t3.field='payment_tokens_client' AND t3.locale='".$booking_arr['locale_id']."'", 'left outer')
					->find($booking_arr['calendar_id'])
					->toArray('email', ',')
					->getData();
				$option_arr = pjOptionModel::factory()->getPairs($booking_arr['calendar_id']);
				
				$tokens = pjAppController::getTokens($booking_arr, $option_arr);
				
				$subject_client = str_replace($tokens['search'], $tokens['replace'], @$calendar_arr['payment_subject_client']);
				$message_client = pjUtil::textToHtml(str_replace($tokens['search'], $tokens['replace'], @$calendar_arr['payment_tokens_client']));
				
				if (!empty($subject_client) && !empty($message_client))
				{
					$from = !empty($calendar_arr['email']) ? $calendar_arr['email'][0] : $booking_arr['c_email'];
					$this->set('arr', array(
							'to' => $booking_arr['c_email'],
							'from' => $from,
							'message' => $message_client,
							'subject' => $subject_client
					));
				}
			} else {
				exit;
			}
		}
	}
}
?>