<?php
if (!defined("ROOT_PATH"))
{
	header("HTTP/1.1 403 Forbidden");
	exit;
}
class pjFront extends pjAppController
{
	public $defaultForm = 'ERent_Form';
	
	public $defaultCaptcha = 'ERent_Captcha';
	
	public $defaultCart = 'ERent_Cart';
	
	public $defaultLocale = 'ERent_LocaleId';
	
	public $defaultLangMenu = 'ERent_LangMenu';
	
	public $cart = NULL;
	
	public function __construct()
	{
		$this->setLayout('pjActionFront');
		if (!isset($_SESSION[$this->defaultCart]))
		{
			$_SESSION[$this->defaultCart] = array();
		}
		
		$this->cart = new pjCart($_SESSION[$this->defaultCart]);
		self::allowCORS();
	}
	
	public function isXHR()
	{
		return parent::isXHR() || isset($_SERVER['HTTP_ORIGIN']);
	}
	
	static protected function allowCORS()
	{
		$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '*';
		header('P3P: CP="ALL DSP COR CUR ADM TAI OUR IND COM NAV INT"');
		header("Access-Control-Allow-Origin: $origin");
		header("Access-Control-Allow-Credentials: true");
		header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
		header("Access-Control-Allow-Headers: Origin, X-Requested-With");
	}
	
	public function afterFilter()
	{
		$locale_arr = pjLocaleModel::factory()->select('t1.*, t2.file, t2.title')
			->join('pjLocaleLanguage', 't2.iso=t1.language_iso', 'left')
			->where('t2.file IS NOT NULL')
			->orderBy('t1.sort ASC')->findAll()->getData();
		
		$this->set('terms_arr', $this->getTerms($this->getForeignId()));
		$this->set('locale_arr', $locale_arr);
	}
	
	public function beforeFilter()
	{
		$pjOptionModel = pjOptionModel::factory();
		$this->option_arr = $pjOptionModel->getPairs($this->getForeignId());
		$this->set('option_arr', $this->option_arr);
		$this->setTime();
		
		if ($this->pjActionGetLocale() === FALSE)
		{
			$locale_arr = pjLocaleModel::factory()->where('is_default', 1)->limit(1)->findAll()->getData();
			if (count($locale_arr) === 1)
			{
				$this->pjActionSetLocale($locale_arr[0]['id']);
			}
		}
		$this->loadSetFields(true);

		if (!isset($_SESSION[$this->defaultForm]))
		{
			$_SESSION[$this->defaultForm] = array(
				'date_from' => NULL,
				'date_to' => NULL,
				'hour_from' => NULL,
				'hour_to' => NULL,
				'minute_from' => NULL,
				'minute_to' => NULL
			);
		}
	}

	public function beforeRender()
	{
		
	}
	
	private function pjActionSetLocale($locale)
	{
		if ((int) $locale > 0)
		{
			$_SESSION[$this->defaultLocale] = (int) $locale;
		}
		return $this;
	}
	
	protected function pjActionGetLocale()
	{
		return isset($_SESSION[$this->defaultLocale]) && (int) $_SESSION[$this->defaultLocale] > 0 ? (int) $_SESSION[$this->defaultLocale] : FALSE;
	}
	public function pjActionLocale()
	{
		$this->setAjax(true);
	
		if ($this->isXHR())
		{
			if (isset($_GET['locale_id']))
			{
				$this->pjActionSetLocale($_GET['locale_id']);
	
				$this->loadSetFields(true);
	
				pjAppController::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Locale have been changed.', 'opts' => array()));
			}
		}
		exit;
	}
	protected function fixDatepickers()
	{
		# Fix datepickers
		$result = $this->getDates();
		$this->set('first_working_date', $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']))
		{
			$this->set('day_limit_start', $this->getDayLimit($_SESSION[$this->defaultForm]['date_from'], $result));
			$this->set('day_limit_end', $this->getDayLimit($_SESSION[$this->defaultForm]['date_to'], $result));
		} else {
			$this->set('day_limit', $this->getDayLimit($result['first_working_date'], $result));
		}
	}
	
	protected function getValidate($summary)
	{
		if ($this->cart->isEmpty())
		{
			return false;
		}

		if (!isset($summary['items']) || empty($summary['items']))
		{
			return false;
		}

		foreach ($summary['items'] as $item)
		{
			$key = $item['type'] . '_' . $item['id'];
			if ((int) $item['unavailable_days'] === 0 && (int) $item['cnt'] >= (int) $item['booked_qty'] + (int) $summary['cart'][$key])
			{
				//ok
			} else {
				// item not available
				return false;
			}
		}
		// Pass all checks
		return true;
	}
	
	protected function getSummary()
	{
		$FORM = @$_SESSION[$this->defaultForm];
		$date_from = $date_to = $dt_from = $dt_to = NULL;
		$tax = $security = $delivery = $collection = $total = $deposit = $price = 0;
		$item_id = $package_id = $i_arr = $p_arr = array();
		
		$back = @$FORM['back'];
		$forth = @$FORM['forth'];
		
		$cart = $this->cart->getAll();
		foreach ($cart as $key => $qty)
		{
			list($type, $id) = explode("_", $key);
			switch ($type)
			{
				case 'item':
					$item_id[] = $id;
					break;
				case 'package':
					$package_id[] = $id;
					break;
			}
		}
		
		if (!empty($item_id) || !empty($package_id))
		{
			$date_from = $FORM['date_from'];
			$date_to = $FORM['date_to'];
			
			$dt_from = $date_from . " " . $FORM['hour_from'] . ":" . $FORM['minute_from'] . ":00";
			$dt_to = $date_to . " " . $FORM['hour_to'] . ":" . $FORM['minute_to'] . ":00";
		}
		
		if (!empty($item_id))
		{
			$i_arr = pjItemModel::factory()
				->select(sprintf("t1.*, t2.content AS `title`, 'item' AS `type`,
					(SELECT `medium_path` FROM `%8\$s`
						WHERE `foreign_id` = `t1`.`id`
						ORDER BY ISNULL(`sort`), `sort` ASC, `id` ASC
						LIMIT 1) AS `pic`,
					(SELECT `small_path` FROM `%8\$s`
						WHERE `foreign_id` = `t1`.`id`
						ORDER BY ISNULL(`sort`), `sort` ASC, `id` ASC
						LIMIT 1) AS `small_pic`,
					(SELECT COUNT(*)
						FROM `%1\$s`
						WHERE `item_id` = t1.id
						AND `dt` BETWEEN '%2\$s' AND '%3\$s'
						LIMIT 1
					) AS `unavailable_days`,
					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 `%9\$s` AS `pi`
								INNER JOIN `%10\$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, pjGalleryModel::factory()->getTable(),
					pjPackageItemModel::factory()->getTable(), pjPackageModel::factory()->getTable()
				))
				->join('pjMultiLang', "t2.model='pjItem' AND t2.foreign_id=t1.id AND t2.locale='".$this->getLocaleId()."' AND t2.field='title'", 'left outer')
				->whereIn('t1.id', $item_id)
				->findAll()
				->getData();
				
			foreach ($i_arr as $k => $v)
			{
				$i_arr[$k]['price'] = $this->getPrice($v['id'], 'item', $dt_from, $dt_to);
			}
		}
		
		if (!empty($package_id))
		{
			$p_arr = pjPackageModel::factory()
				->select(sprintf("t1.*, t2.content AS `title`, 'package' AS `type`,
					(SELECT `medium_path` FROM `%10\$s`
						WHERE `foreign_id` IN (SELECT `item_id` FROM `%9\$s` WHERE `package_id` = `t1`.`id`)
						AND `medium_path` IS NOT NULL
						ORDER BY ISNULL(`sort`), `sort` ASC, `id` ASC
						LIMIT 1) AS `pic`,
					(SELECT `small_path` FROM `%10\$s`
						WHERE `foreign_id` IN (SELECT `item_id` FROM `%9\$s` WHERE `package_id` = `t1`.`id`)
						AND `medium_path` IS NOT NULL
						ORDER BY ISNULL(`sort`), `sort` ASC, `id` ASC
						LIMIT 1) AS `small_pic`,
					(SELECT COUNT(*)
						FROM `%1\$s`
						WHERE `package_id` = t1.id
						AND `dt` BETWEEN '%2\$s' AND '%3\$s'
						LIMIT 1
					) AS `unavailable_days`,
					(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`
					",
					pjPackageAvailabilityModel::factory()->getTable(), $date_from, $date_to,
					pjBookingItemModel::factory()->getTable(), pjBookingModel::factory()->getTable(),
					$dt_from, $dt_to, pjItemModel::factory()->getTable(), pjPackageItemModel::factory()->getTable(),
					pjGalleryModel::factory()->getTable()
				))
				->join('pjMultiLang', "t2.model='pjPackage' AND t2.foreign_id=t1.id AND t2.locale='".$this->getLocaleId()."' AND t2.field='title'", 'left outer')
				->whereIn('t1.id', $package_id)
				->findAll()
				->getData();
			
			foreach ($p_arr as $k => $v)
			{
				$p_arr[$k]['price'] = $this->getPrice($v['id'], 'package', $dt_from, $dt_to);
			}
		}
		$items = array_merge($i_arr, $p_arr);
		
		foreach ($items as $item)
		{
			$key = $item['type']."_".$item['id'];
			$price += @$item['price'] * (int) $cart[$key];
		}
		
		if (isset($FORM['forth']) && $FORM['forth'] == 'delivery')
		{
			$delivery = (float) $this->option_arr['o_delivery'];
		}
		if (isset($FORM['back']) && $FORM['back'] == 'collection')
		{
			$collection = (float) $this->option_arr['o_collection'];
		}
		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'];
		}
		$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;
		
		return compact('cart', 'items', 'dt_from', 'dt_to', 'date_from', 'date_to', 'back', 'forth',
			'tax', 'security', 'delivery', 'collection', 'total', 'deposit', 'price');
	}
	
	protected function getTerms($cid)
	{
		return pjCalendarModel::factory()
			->select('t1.*, t2.content AS terms_url, t3.content AS terms_body')
			->join('pjMultiLang', "t2.model='pjCalendar' AND t2.foreign_id=t1.id AND t2.field='terms_url' AND t2.locale='".$this->pjActionGetLocale()."'", 'left outer')
			->join('pjMultiLang', "t3.model='pjCalendar' AND t3.foreign_id=t1.id AND t3.field='terms_body' AND t3.locale='".$this->pjActionGetLocale()."'", 'left outer')
			->find($cid)
			->getData();
	}

	protected function getDates()
	{
		$days_off = $dates_off = $dates_on = $default_times = $custom_times = array();
		$w_arr = pjCalendarModel::factory()->find($this->getForeignId())->getData();
		if (!empty($w_arr))
		{
			$default_times[1] = array('start' => $w_arr['monday_from'], 'end' => $w_arr['monday_to']);
			$default_times[2] = array('start' => $w_arr['tuesday_from'], 'end' => $w_arr['tuesday_to']);
			$default_times[3] = array('start' => $w_arr['wednesday_from'], 'end' => $w_arr['wednesday_to']);
			$default_times[4] = array('start' => $w_arr['thursday_from'], 'end' => $w_arr['thursday_to']);
			$default_times[5] = array('start' => $w_arr['friday_from'], 'end' => $w_arr['friday_to']);
			$default_times[6] = array('start' => $w_arr['saturday_from'], 'end' => $w_arr['saturday_to']);
			$default_times[0] = array('start' => $w_arr['sunday_from'], 'end' => $w_arr['sunday_to']);
			
			if ($w_arr['monday_dayoff'] == 'T')
			{
				$days_off[] = 1;
				$default_times[1] = array('start' => NULL, 'end' => NULL);
			}
			if ($w_arr['tuesday_dayoff'] == 'T')
			{
				$days_off[] = 2;
				$default_times[2] = array('start' => NULL, 'end' => NULL);
			}
			if ($w_arr['wednesday_dayoff'] == 'T')
			{
				$days_off[] = 3;
				$default_times[3] = array('start' => NULL, 'end' => NULL);
			}
			if ($w_arr['thursday_dayoff'] == 'T')
			{
				$days_off[] = 4;
				$default_times[4] = array('start' => NULL, 'end' => NULL);
			}
			if ($w_arr['friday_dayoff'] == 'T')
			{
				$days_off[] = 5;
				$default_times[5] = array('start' => NULL, 'end' => NULL);
			}
			if ($w_arr['saturday_dayoff'] == 'T')
			{
				$days_off[] = 6;
				$default_times[6] = array('start' => NULL, 'end' => NULL);
			}
			if ($w_arr['sunday_dayoff'] == 'T')
			{
				$days_off[] = 0;
				$default_times[0] = array('start' => NULL, 'end' => NULL);
			}
		}
		
		$d_arr = pjDateModel::factory()
			->where('t1.calendar_id', $this->getForeignId())
			->where('t1.date >= CURDATE()')
			->findAll()
			->getData();

		foreach ($d_arr as $date)
		{
			if ($date['is_dayoff'] == 'T')
			{
				$dates_off[] = $date['date'];
			} else {
				$dates_on[] = $date['date'];
				
				$custom_times[$date['date']] = array(
					'start' => $date['start_time'],
					'end' => $date['end_time']
				);
			}
		}

		# Find first working day starting from today
		$first_working_date = NULL;
		list($y, $m, $d, $w) = explode("-", date("Y-n-j-w"));
		foreach (range(0, 365) as $i)
		{
			$timestamp = mktime(0, 0, 0, $m, $d + $i, $y);
			list($date, $wday) = explode("|", date("Y-m-d|w", $timestamp));
			
			if (!in_array($wday, $days_off) && !in_array($date, $dates_off))
			{
				$first_working_date = $date;
				break;
			}
			
			if (in_array($wday, $days_off) && in_array($date, $dates_on))
			{
				$first_working_date = $date;
				break;
			}
		}
		
		return compact('first_working_date', 'days_off', 'dates_off', 'dates_on', 'default_times', 'custom_times');
	}
	
	protected function getDayLimit($iso_date, $result=NULL)
	{
		if (is_null($result))
		{
			$result = $this->getDates();
		}
		
		if (isset($result['custom_times'][$iso_date]))
		{
			return $result['custom_times'][$iso_date];
		} else {
			$w = date("w", strtotime($iso_date));
			if (isset($result['default_times'][$w]))
			{
				return $result['default_times'][$w];
			}
		}
		
		return FALSE;
	}
	
	protected function getDateOffInRange($date_from, $date_to)
	{
		$result = $this->getDates();
		
		$time_from = strtotime($date_from);
		$time_to = strtotime($date_to);
		
		foreach ($result['dates_off'] as $date)
		{
			$time = strtotime($date);
			if ($time >= $time_from && $time <= $time_to)
			{
				return TRUE;
			}
		}

		foreach ($result['days_off'] as $week_day)
		{
			for ($i = $time_from; $i <= $time_to; $i += 86400)
			{
				if ($week_day == date("w", $i))
				{
					return TRUE;
				}
			}
		}
		
		return FALSE;
	}
}
?>