<?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 function isOneAdminReady()
	{
		return $this->isAdmin();
	}
	public function isCountryReady()
    {
    	return $this->isAdmin();
    }
	
	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 isEditor()
    {
    	return $this->getRoleId() == 2;
    }
    
	public function isAgent()
    {
    	return $this->getRoleId() == 3;
    }
    
	public function isViewer()
    {
    	return $this->getRoleId() == 4;
    }
    
    public function getForeignId()
    {
    	return 1;
    }
    
    public function beforeFilter()
    {
    	$this->appendJs('jquery.min.js', PJ_THIRD_PARTY_PATH . 'jquery/');
    	$dm = new pjDependencyManager(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 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 getLocaleId()
	{
		return isset($_SESSION[$this->defaultLocale]) && (int) $_SESSION[$this->defaultLocale] > 0 ? (int) $_SESSION[$this->defaultLocale] : false;
	}
	public function getDirection()
	{
		$dir = 'ltr';
		if($this->getLocaleId() != false)
		{
			$locale_arr = pjLocaleModel::factory()->find($this->getLocaleId())->getData();
			$dir = $locale_arr['dir'];
		}
		return $dir;
	}
	public function setLocaleId($locale_id)
	{
		$_SESSION[$this->defaultLocale] = (int) $locale_id;
	}
	
	public function friendlyURL($str, $divider='-')
	{
		$str = mb_strtolower($str, mb_detect_encoding($str));
		$str = trim($str);
		$str = preg_replace('/[_|\s]+/', $divider, $str);
		$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);
		$str = preg_replace('/[-]+/', $divider, $str);
		$str = preg_replace('/^-+|-+$/', '', $str);
		return $str;
	}
	
	public function pjActionCheckInstall()
	{
		$this->setLayout('pjActionEmpty');
		
		$result = array('status' => 'OK', 'code' => 200, 'text' => 'Operation succeeded', 'info' => array());
		$folders = array(
							'app/web/upload',
							'app/web/upload/bus_types'
						);
		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 getData($option_arr, $booking_arr, $salt, $locale_id)
	{
		$country = $pickup_area = NULL;
		if (isset($booking_arr['c_country']) && !empty($booking_arr['c_country']))
		{
			$country_arr = pjCountryModel::factory()
						->select('t1.id, t2.content AS country_title')
						->join('pjMultiLang', "t2.model='pjCountry' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='".$locale_id."'", 'left outer')
						->find($booking_arr['c_country'])->getData();
			if (!empty($country_arr))
			{
				$country = $country_arr['country_title'];
			}
		}
		
		if (isset($booking_arr['pickup_area_id']) && !empty($booking_arr['pickup_area_id']))
		{
			$area_arr = pjAreaModel::factory()
						->select('t1.id, t2.content AS area')
						->join('pjMultiLang', "t2.model='pjArea' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='".$locale_id."'", 'left outer')
						->find($booking_arr['pickup_area_id'])->getData();
			if (!empty($area_arr))
			{
				$pickup_area = $area_arr['area'];
			}
		}
		
		$seats = '';
		$booked_seat_id_arr = pjBookingSeatModel::factory()
			->select("DISTINCT (seat_id), name")
			->where('booking_id', $booking_arr['id'])
			->findAll()
			->getDataPair('seat_id', 'name');
		if(!empty($booked_seat_id_arr))
		{
			$selected_seat_arr = pjSeatModel::factory()->whereIn('t1.id', array_keys($booked_seat_id_arr))->findAll()->getDataPair('id', 'name');
			$bs_arr = array();
			foreach ($selected_seat_arr as $sid => $sname) {
				$bs_arr[] = $sname.'('.$booked_seat_id_arr[$sid].')';
			}
			$seats = join(", ", $bs_arr);
		}
		
		$row = $ticket_type_arr = array();
		$totalTicketType = 0;
		if (isset($booking_arr['tickets']))
		{
			$ticket_arr = $booking_arr['tickets'];
			foreach ($ticket_arr as $v)
			{
				if($v['qty'] > 0)
				{
					$price = $v['amount'] / $v['qty'];
					$amount = $v['amount'];
					if(isset($v['price']))
					{
						$price = $v['price'];
						$amount = $price * $v['qty'];
					}
					$totalTicketType += $v['qty']; 
					$row[] = stripslashes($v['title']) . ' '.$v['qty'].' x '.pjUtil::formatCurrencySign(number_format($price, 2, ".", "."), $option_arr['o_currency']) . ' = ' . pjUtil::formatCurrencySign(number_format($amount, 2), $option_arr['o_currency']);
					$ticket_type_arr[] = stripslashes($v['title']) . ' '.$v['qty'];
				}
			}
		}
		$tickets = count($row) > 0 ? join("<br/>", $row) : NULL;
		$ticket_type = count($ticket_type_arr) > 0 ? join("<br/>", $ticket_type_arr) : NULL;
		
		$bus = @$booking_arr['route_title'] . ', ' . date($option_arr['o_time_format'], strtotime(@$booking_arr['departure_time'])) . ' - ' . date($option_arr['o_time_format'], strtotime(@$booking_arr['arrival_time']));
		$route = mb_strtolower(__('lblFrom', true), 'UTF-8') . ' ' . @$booking_arr['from_location'] . ' ' . mb_strtolower(__('lblTo', true), 'UTF-8') . ' ' . @$booking_arr['to_location'];
		
		$time = $booking_arr['booking_time'];
		$time_arr = explode(" - ", $time);
		$total = pjUtil::formatCurrencySign(number_format($booking_arr['total'], 2, ".", "."), $option_arr['o_currency']);
		$discount = pjUtil::formatCurrencySign(number_format($booking_arr['voucher_value'], 2, ".", "."), $option_arr['o_currency']);
		$tax = pjUtil::formatCurrencySign(number_format($booking_arr['tax'], 2, ".", "."), $option_arr['o_currency']);
		
		$booking_date = $return_date = $from_location = $to_location = NULL;
		if (isset($booking_arr['booking_date']) && !empty($booking_arr['booking_date']))
		{
			$tm = strtotime(@$booking_arr['booking_date']);
			$booking_date = date($option_arr['o_date_format'], $tm);
		}
		if (isset($booking_arr['return_date']) && !empty($booking_arr['return_date']))
		{
			$tm = strtotime(@$booking_arr['return_date']);
			$return_date = date($option_arr['o_date_format'], $tm);
		}
		$from_location = @$booking_arr['from_location'];
		$to_location = @$booking_arr['to_location'];
		$personal_titles = __('personal_titles', true, false);
		
		$return_from_location = $return_to_location = $return_departure_time = $return_arrival_time = '';
		if ($booking_arr['is_return'] == 'T' && (int)$booking_arr['back_id'] > 0) {
			$return_from_location = $to_location;
			$return_to_location = $from_location;
			$back_booking_arr = pjBookingModel::factory()->reset()->find($booking_arr['back_id'])->getData();
			$return_time = $back_booking_arr['booking_time'];
			$return_time_arr = explode(" - ", $return_time);
			$return_departure_time = @$return_time_arr[0];
			$return_arrival_time = @$return_time_arr[1];
		}
		
		$cancelURL = PJ_INSTALL_URL . 'index.php?controller=pjFrontEnd&action=pjActionCancel&id='.@$booking_arr['id'].'&hash='.sha1(@$booking_arr['id'].@$booking_arr['created'].$salt);
		$printURL = PJ_INSTALL_URL . 'index.php?controller=pjFrontEnd&action=pjActionPrintTickets&id='.@$booking_arr['id'].'&hash='.sha1(@$booking_arr['id'].@$booking_arr['created'].$salt);
		$cancelURL = '<a href="'.$cancelURL.'">'.$cancelURL.'</a>';
		$printURL = '<a href="'.$printURL.'">'.$printURL.'</a>';
		$search = array(
			'{Title}', '{FirstName}', '{LastName}', '{Email}', '{Phone}', '{Country}',
			'{City}', '{State}', '{Zip}', '{Address}',
			'{Company}', '{CCType}', '{CCNum}', '{CCExp}','{CCSec}', '{PaymentMethod}',
			'{UniqueID}', '{Date}', '{Bus}', '{Route}', '{Seats}', '{Time}', '{TicketType}', '{TicketTypesPrice}', '{TotalTicketType}',
			'{Total}', '{Tax}', '{Notes}',
			'{PrintTickets}',
			'{CancelURL}', '{From_Location}', '{To_Location}', '{Return_Date}', '{DiscountCode}', '{DiscountValue}', '{PickupArea}',
			'{Departure_Time}', '{Arrival_Time}', '{Return_From_Location}', '{Return_To_Location}', '{Return_Departure_Time}', '{Return_Arrival_Time}'
		);
		$replace = array(
			(!empty($booking_arr['c_title']) ? $personal_titles[$booking_arr['c_title']] : null), $booking_arr['c_fname'], $booking_arr['c_lname'], $booking_arr['c_email'], $booking_arr['c_phone'], $country,
			$booking_arr['c_city'], $booking_arr['c_state'], $booking_arr['c_zip'], $booking_arr['c_address'],
			$booking_arr['c_company'], @$booking_arr['cc_type'], @$booking_arr['cc_num'], (@$booking_arr['payment_method'] == 'creditcard' ? @$booking_arr['cc_exp'] : NULL), @$booking_arr['cc_code'], @$booking_arr['payment_method'],
			@$booking_arr['uuid'], $booking_date, $bus, $route, $seats, $time, $ticket_type, $tickets, $totalTicketType, 
			@$total, $tax, @$booking_arr['c_notes'],
			$printURL,
			$cancelURL, $from_location, $to_location, $return_date, @$booking_arr['voucher_code'], $discount, $pickup_area,
			@$time_arr[0], @$time_arr[1], $return_from_location, $return_to_location, $return_departure_time, $return_arrival_time
		);

		return compact('search', 'replace');
	}
	
	public function getTemplate($option_arr, $booking_arr, $salt, $locale_id)
	{
		$country = $pickup_area = NULL;
		if (isset($booking_arr['c_country']) && !empty($booking_arr['c_country']))
		{
			$country_arr = pjCountryModel::factory()
						->select('t1.id, t2.content AS country_title')
						->join('pjMultiLang', "t2.model='pjCountry' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='".$locale_id."'", 'left outer')
						->find($booking_arr['c_country'])->getData();
			if (!empty($country_arr))
			{
				$country = $country_arr['country_title'];
			}
		}
		
		if (isset($booking_arr['pickup_area_id']) && !empty($booking_arr['pickup_area_id']))
		{
			$area_arr = pjAreaModel::factory()
						->select('t1.id, t2.content AS area')
						->join('pjMultiLang', "t2.model='pjArea' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='".$locale_id."'", 'left outer')
						->find($booking_arr['pickup_area_id'])->getData();
			if (!empty($area_arr))
			{
				$pickup_area = $area_arr['area'];
			}
		}
		
		$seats = '';
		$booked_seat_id_arr = pjBookingSeatModel::factory()
			->select("DISTINCT (seat_id), name")
			->where('booking_id', $booking_arr['id'])
			->findAll()
			->getDataPair('seat_id', 'name');
		if(!empty($booked_seat_id_arr))
		{
			$selected_seat_arr = pjSeatModel::factory()->whereIn('t1.id', array_keys($booked_seat_id_arr))->findAll()->getDataPair('id', 'name');
			$bs_arr = array();
			foreach ($selected_seat_arr as $sid => $sname) {
				$bs_arr[] = $sname.'('.$booked_seat_id_arr[$sid].')';
			}
			$seats = join(", ", $bs_arr);
		}
		$row = array();
		$totalTicketType = 0;
		if (isset($booking_arr['tickets']))
		{
			$ticket_arr = $booking_arr['tickets'];
			foreach ($ticket_arr as $v)
			{
				if($v['qty'] > 0)
				{
					$price = $v['amount']/$v['qty'];
					$row[] = stripslashes($v['title']) . ' '.$v['qty'];
					$totalTicketType += $v['qty'];
				}
			}
		}
		$ticket_type = count($row) > 0 ? join("<br/>", $row) : NULL;

		$booking_route_arr = explode("<br/>", $booking_arr['booking_route']);
		$bus = $booking_route_arr[0];
		$route = $booking_route_arr[1];
		$time = $booking_arr['booking_time'];
		$total = pjUtil::formatCurrencySign(number_format($booking_arr['total'], 2, ".", "."), $option_arr['o_currency']);
		$discount = pjUtil::formatCurrencySign(number_format($booking_arr['voucher_value'], 2, ".", "."), $option_arr['o_currency']);
		$tax = pjUtil::formatCurrencySign(number_format($booking_arr['tax'], 2, ".", "."), $option_arr['o_currency']);
		
		$time_arr = explode(" - ", $time);
		
		$booking_date = $return_date = NULL;
		if (isset($booking_arr['booking_date']) && !empty($booking_arr['booking_date']))
		{
			$tm = strtotime(@$booking_arr['booking_date']);
			$booking_date = date($option_arr['o_date_format'], $tm);
		}
		if (isset($booking_arr['return_date']) && !empty($booking_arr['return_date']))
		{
			$tm = strtotime(@$booking_arr['return_date']);
			$return_date = date($option_arr['o_date_format'], $tm);
		}
		$personal_titles = __('personal_titles', true, false);
		$from_location = @$booking_arr['from_location'];
		$to_location = @$booking_arr['to_location'];
		
		$return_from_location = $return_to_location = $return_departure_time = $return_arrival_time = '';
		if ($booking_arr['is_return'] == 'T' && (int)$booking_arr['back_id'] > 0) {
			$return_from_location = $to_location;
			$return_to_location = $from_location;
			$back_booking_arr = pjBookingModel::factory()->reset()->find($booking_arr['back_id'])->getData();
			$return_time = $back_booking_arr['booking_time'];
			$return_time_arr = explode(" - ", $return_time);
			$return_departure_time = @$return_time_arr[0];
			$return_arrival_time = @$return_time_arr[1];
		}
		
		$cancelURL = PJ_INSTALL_URL . 'index.php?controller=pjFrontEnd&action=pjActionCancel&id='.@$booking_arr['id'].'&hash='.sha1(@$booking_arr['id'].@$booking_arr['created'].$salt);
		$search = array(
			'{Title}', '{FirstName}', '{LastName}', '{Email}', '{Phone}', '{Country}',
			'{City}', '{State}', '{Zip}', '{Address}',
			'{Company}', '{CCType}', '{CCNum}', '{CCExp}','{CCSec}', '{PaymentMethod}',
			'{UniqueID}', '{Date}', '{Bus}', '{Route}', '{Seat}', '{Time}',
			'{From_Location}', '{To_Location}', '{Departure_Time}', '{Arrival_Time}',
			'{TicketType}', '{TotalTicketType}',
			'{Total}', '{Tax}', '{Notes}',
			'{CancelURL}', '{Return_Date}', '{DiscountCode}', '{DiscountValue}', '{PickupArea}',
			'{Return_From_Location}', '{Return_To_Location}', '{Return_Departure_Time}', '{Return_Arrival_Time}'
		);
		$replace = array(
			(!empty($booking_arr['c_title']) ? $personal_titles[$booking_arr['c_title']] : null), $booking_arr['c_fname'], $booking_arr['c_lname'], $booking_arr['c_email'], $booking_arr['c_phone'], $country,
			$booking_arr['c_city'], $booking_arr['c_state'], $booking_arr['c_zip'], $booking_arr['c_address'],
			$booking_arr['c_company'], @$booking_arr['cc_type'], @$booking_arr['cc_num'], (@$booking_arr['payment_method'] == 'creditcard' ? @$booking_arr['cc_exp'] : NULL), @$booking_arr['cc_code'], @$booking_arr['payment_method'],
			@$booking_arr['uuid'], $booking_date, $bus, $route, $seats, $time,
			$from_location, $to_location, @$time_arr[0], @$time_arr[1],
			$ticket_type, $totalTicketType, 
			@$total, $tax, @$booking_arr['c_notes'],
			@$cancelURL, $return_date, @$booking_arr['voucher_code'], $discount, $pickup_area,
			$return_from_location, $return_to_location, $return_departure_time, $return_arrival_time
		);

		return compact('search', 'replace');
	}
	
	public function getAdminEmail()
	{
		$arr = pjUserModel::factory()->find(1)->getData();
		return $arr['email'];
	}
	public function getAdminPhone()
	{
		$arr = pjUserModel::factory()->find(1)->getData();
		return !empty($arr['phone']) ? $arr['phone'] : null;
	}
	public function getAllEmails()
	{
		$user_arr = pjUserModel::factory()->where('t1.status', 'T')->findAll()->getData();
		$arr = array();
		foreach($user_arr as $v)
		{
			if(!empty($v['email']))
			{
				$arr[] = $v['email'];
			}
		}
		return $arr;
	}
	public function getAllPhones()
	{
		$user_arr = pjUserModel::factory()->where('t1.status', 'T')->findAll()->getData();
		$arr = array();
		foreach($user_arr as $v)
		{
			if(!empty($v['phone']))
			{
				$arr[] = $v['phone'];
			}
		}
		return $arr;
	}

	public function getBusAvailability($bus_id, $store, $option_arr) {
		$pickup_id = $store ['pickup_id'];
		$return_id = $store ['return_id'];
		$booked_seat_arr = array ();
		$bus_type_arr = array ();
		
		$bus_arr = pjBusModel::factory ()->find ( $bus_id )->getData ();
		$departure_time = null;
		$arrival_time = null;
		if (isset ( $store ['booking_period'] [$bus_id] )) {
			if (isset ( $store ['booking_period'] [$bus_id] ['departure_time'] )) {
				$departure_time = $store ['booking_period'] [$bus_id] ['departure_time'];
			}
			if (isset ( $store ['booking_period'] [$bus_id] ['arrival_time'] )) {
				$arrival_time = $store ['booking_period'] [$bus_id] ['arrival_time'];
			}
		}
		$and_where = '';
		if ($departure_time != null && $arrival_time != null) {
			$and_where .= " AND ((TB.booking_datetime BETWEEN '$departure_time' AND '$arrival_time') OR (TB.stop_datetime BETWEEN '$departure_time' AND '$arrival_time' ) OR ('$departure_time' BETWEEN TB.booking_datetime AND TB.stop_datetime ) OR ('$arrival_time' BETWEEN TB.booking_datetime AND TB.stop_datetime ))";
		}
		
		if (! empty ( $bus_arr )) {
			$location_id_arr = pjRouteCityModel::factory ()->getLocationIdPair ( $bus_arr ['route_id'], $pickup_id, $return_id );
			
			$booked_seat_arr = pjBookingSeatModel::factory ()->select ( "DISTINCT seat_id" )->where ( "t1.booking_id IN(SELECT TB.id
										  FROM `" . pjBookingModel::factory ()->getTable () . "` AS TB
										  WHERE (TB.status='confirmed' OR (TB.status='pending' AND UNIX_TIMESTAMP(TB.created) >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL " . $option_arr ['o_min_hour'] . " MINUTE))))
					AND TB.bus_id = $bus_id $and_where)
					AND start_location_id IN(" . join ( ",", $location_id_arr ) . ")" )->findAll ()->getDataPair ( "seat_id", "seat_id" );
			
			$bus_type_arr = pjBusTypeModel::factory ()->find ( $bus_arr ['bus_type_id'] )->getData ();
		}
		
		return compact ( 'booked_seat_arr', 'bus_type_arr' );
	}
	public function getReturnBusAvailability($bus_id, $store, $option_arr) {
		$pickup_id = $store ['return_id'];
		$return_id = $store ['pickup_id'];
		$booked_seat_arr = array ();
		$bus_type_arr = array ();
		
		$bus_arr = pjBusModel::factory ()->find ( $bus_id )->getData ();
		
		$departure_time = null;
		$arrival_time = null;
		if (isset ( $store ['booking_period'] [$bus_id] )) {
			if (isset ( $store ['booking_period'] [$bus_id] ['departure_time'] )) {
				$departure_time = $store ['booking_period'] [$bus_id] ['departure_time'];
			}
			if (isset ( $store ['booking_period'] [$bus_id] ['arrival_time'] )) {
				$arrival_time = $store ['booking_period'] [$bus_id] ['arrival_time'];
			}
		}
		$and_where = '';
		if ($departure_time != null && $arrival_time != null) {
			$and_where .= " AND ((TB.booking_datetime BETWEEN '$departure_time' AND '$arrival_time') OR (TB.stop_datetime BETWEEN '$departure_time' AND '$arrival_time' ) OR ('$departure_time' BETWEEN TB.booking_datetime AND TB.stop_datetime ) OR ('$arrival_time' BETWEEN TB.booking_datetime AND TB.stop_datetime ))";
		}
		if (! empty ( $bus_arr )) {
			$location_id_arr = pjRouteCityModel::factory ()->getLocationIdPair ( $bus_arr ['route_id'], $pickup_id, $return_id );
			
			$booked_seat_arr = pjBookingSeatModel::factory ()->select ( "DISTINCT seat_id" )->where ( "t1.booking_id IN(SELECT TB.id
										  FROM `" . pjBookingModel::factory ()->getTable () . "` AS TB
											  WHERE (TB.status='confirmed' OR (TB.status='pending' AND UNIX_TIMESTAMP(TB.created) >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL " . $option_arr ['o_min_hour'] . " MINUTE))))
												  		AND TB.bus_id = $bus_id $and_where)
												  		AND start_location_id IN('" . join ( "', '", $location_id_arr ) . "')" )->findAll ()->getDataPair ( "seat_id", "seat_id" );
			
			$bus_type_arr = pjBusTypeModel::factory ()->find ( $bus_arr ['bus_type_id'] )->getData ();
		}
		
		return compact ( 'booked_seat_arr', 'bus_type_arr' );
	}
	public function isBusReady() {
		$cnt_cities = pjCityModel::factory ()->where ( 'status', 'T' )->findCount ()->getData ();
		$cnt_bus_types = pjBusTypeModel::factory ()->where ( 'status', 'T' )->findCount ()->getData ();
		$cnt_routes = pjRouteModel::factory ()->where ( 'status', 'T' )->findCount ()->getData ();
		$cnt_routes_cities = pjRouteCityModel::factory ()->findCount ()->getData ();
		$cnt_route_details = pjRouteDetailModel::factory ()->findCount ()->getData ();
		$cnt_buses = pjBusModel::factory ()->findCount ()->getData ();
		
		if ($cnt_cities > 0 && $cnt_bus_types > 0 && $cnt_routes > 0 && $cnt_routes_cities > 0 && $cnt_route_details > 0 && $cnt_buses > 0) {
			return true;
		} else {
			return false;
		}
	}
	public function getBusList($pickup_id, $return_id, $bus_id_arr, $booking_period, $booked_data, $date, $is_return, $locale_id=1) {
		$pjBusLocationModel = pjBusLocationModel::factory ();
		$pjPriceModel = pjPriceModel::factory ();
		$pjBookingSeatModel = pjBookingSeatModel::factory ();
		$pjBookingModel = pjBookingModel::factory ();
		$pjBusTypeModel = pjBusTypeModel::factory ();
		$pjRouteCityModel = pjRouteCityModel::factory ();
		$pjSeatModel = pjSeatModel::factory ();
		$pjCityModel = pjCityModel::factory ();
		
		$pickup_location = $pjCityModel->reset ()->select ( 't1.*, t2.content as name' )->join ( 'pjMultiLang', "t2.model='pjCity' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='" . $this->getLocaleId () . "'", 'left outer' )->find ( $pickup_id )->getData ();
		$return_location = $pjCityModel->reset ()->select ( 't1.*, t2.content as name' )->join ( 'pjMultiLang', "t2.model='pjCity' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='" . $this->getLocaleId () . "'", 'left outer' )->find ( $return_id )->getData ();
		
		$ticket_columns = 0;
		$booking_date = pjUtil::formatDate ( $date, $this->option_arr ['o_date_format'] );
		
		$bus_arr = pjBusModel::factory ()->join ( 'pjMultiLang', "t2.model='pjRoute' AND t2.foreign_id=t1.route_id AND t2.field='title' AND t2.locale='" . $this->getLocaleId () . "'", 'left outer' )->join ( 'pjBusType', "t3.id=t1.bus_type_id", 'left outer' )->select ( " t1.*, t2.content AS route, t3.seats_map" )->where ( "(t1.id IN(" . join ( ',', $bus_id_arr ) . "))" )->index ( "FORCE KEY (`bus_type_id`)" )->orderBy ( "route asc" )->findAll ()->getData ();
		
		$location_id_arr = array ();
		foreach ( $bus_arr as $k => $bus ) {
			$locations = $pjRouteCityModel->reset ()->join ( 'pjMultiLang', "t2.model='pjCity' AND t2.foreign_id=t1.city_id AND t2.field='name' AND t2.locale='" . $this->getLocaleId () . "'", 'left outer' )->join ( 'pjBusLocation', "(t3.bus_id='" . $bus ['id'] . "' AND t3.location_id=t1.city_id", 'inner' )->select ( "t1.*, t2.content, t3.departure_time, t3.arrival_time" )->where ( 't1.route_id', $bus ['route_id'] )->orderBy ( "`order` ASC" )->findAll ()->getData ();
			
			$bus ['locations'] = $locations;
			
			if (! empty ( $bus ['start_date'] ) && ! empty ( $bus ['end_date'] )) {
				$bus ['from_to'] = pjUtil::formatDate ( $bus ['start_date'], "Y-m-d", $this->option_arr ['o_date_format'] ) . ' - ' . pjUtil::formatDate ( $bus ['end_date'], "Y-m-d", $this->option_arr ['o_date_format'] );
			} else {
				$bus ['from_to'] = '';
			}
			if (! empty ( $bus ['departure'] ) && ! empty ( $bus ['arrive'] )) {
				$bus ['depart_arrive'] = pjUtil::formatTime ( $bus ['departure'], "H:i:s", $this->option_arr ['o_time_format'] ) . ' - ' . pjUtil::formatTime ( $bus ['arrive'], "H:i:s", $this->option_arr ['o_time_format'] );
			} else {
				$bus ['depart_arrive'] = '';
			}
			$bus_arr [$k] = $bus;
			
			$bus_id = $bus ['id'];
			
			$seat_booked_arr = array ();
			$seat_avail_arr = array ();
			$departure_time = '';
			$arrival_time = '';
			$duration = '';
			
			$pickup_arr = $pjBusLocationModel->reset ()->where ( 'bus_id', $bus_id )->where ( "location_id", $pickup_id )->limit ( 1 )->findAll ()->getData ();
			$return_arr = $pjBusLocationModel->reset ()->where ( 'bus_id', $bus_id )->where ( "location_id", $return_id )->limit ( 1 )->findAll ()->getData ();
			
			if (! empty ( $pickup_arr )) {
				$departure_time = pjUtil::formatTime ( $pickup_arr [0] ['departure_time'], 'H:i:s', $this->option_arr ['o_time_format'] );
				$booking_period [$bus_id] ['departure_time'] = $booking_date . ' ' . $pickup_arr [0] ['departure_time'];
			}
			if (! empty ( $return_arr )) {
				$arrival_time = pjUtil::formatTime ( $return_arr [0] ['arrival_time'], 'H:i:s', $this->option_arr ['o_time_format'] );
			}
			if (! empty ( $pickup_arr ) && ! empty ( $return_arr )) {
				$seconds = 0;
				$start_count = false;
				foreach ( $locations as $key => $lo ) {
					$next_location = $locations [$key + 1];
					
					if ($lo ['city_id'] == $pickup_id) {
						$start_count = true;
					}
					if (isset ( $next_location ) && $start_count == true) {
						$seconds += pjUtil::calSeconds ( $lo ['departure_time'], $next_location ['arrival_time'] );
						if ($key + 1 < count ( $locations ) && $key > 0 && $lo ['city_id'] != $pickup_id) {
							$seconds += pjUtil::calSeconds ( $lo ['arrival_time'], $lo ['departure_time'] );
						}
					}
					if ($next_location ['city_id'] == $return_id) {
						break;
					}
				}
				
				$minutes = ($seconds / 60) % 60;
				$hours = floor ( $seconds / (60 * 60) );
				
				$hour_str = $hours . ' ' . ($hours != 1 ? strtolower ( __ ( 'front_hours', true, false ) ) : strtolower ( __ ( 'front_hour', true, false ) ));
				$minute_str = $minutes > 0 ? '<br/>' . ($minutes . ' ' . ($minutes != 1 ? strtolower ( __ ( 'front_minutes', true, false ) ) : strtolower ( __ ( 'front_minute', true, false ) ))) : '';
				$duration = $hour_str . $minute_str;
				
				if (isset ( $booking_period [$bus_id] ['departure_time'] )) {
					$booking_period [$bus_id] ['arrival_time'] = date ( 'Y-m-d H:i:s', strtotime ( $booking_period [$bus_id] ['departure_time'] ) + $seconds );
				}
			}
			
			$temp_location_id_arr = $pjRouteCityModel->getLocationIdPair ( $bus ['route_id'], $pickup_id, $return_id );
			
			if (! empty ( $booked_data )) {
				if ($is_return == 'F') {
					if ($booked_data ['bus_id'] == $bus_id && empty ( $location_id_arr )) {
						$location_id_arr = $temp_location_id_arr;
					}
				} else {
					if ($booked_data ['return_bus_id'] == $bus_id && empty ( $location_id_arr )) {
						$location_id_arr = $temp_location_id_arr;
					}
				}
			}
			
			if (! empty ( $temp_location_id_arr )) {
				$ticket_price_arr = $pjPriceModel->getTicketPrice ( $bus_id, $pickup_id, $return_id, $booked_data, $this->option_arr, $this->getLocaleId (), $is_return );
				$ticket_arr = $ticket_price_arr ['ticket_arr'];
				
				if ($bus ['set_seats_count'] == 'F') {
					$departure_time = null;
					$arrival_time = null;
					if (isset ( $booking_period [$bus_id] )) {
						if (isset ( $booking_period [$bus_id] ['departure_time'] )) {
							$departure_time = $booking_period [$bus_id] ['departure_time'];
						}
						if (isset ( $booking_period [$bus_id] ['arrival_time'] )) {
							$arrival_time = $booking_period [$bus_id] ['arrival_time'];
						}
					}
					$and_where = '';
					if ($departure_time != null && $arrival_time != null) {
						$and_where .= " AND ((TB.booking_datetime BETWEEN '$departure_time' AND '$arrival_time') OR (TB.stop_datetime BETWEEN '$departure_time' AND '$arrival_time' ) OR ('$departure_time' BETWEEN TB.booking_datetime AND TB.stop_datetime ) OR ('$arrival_time' BETWEEN TB.booking_datetime AND TB.stop_datetime ))";
					}
					$bus_type_arr = $pjBusTypeModel->reset ()->find ( $bus ['bus_type_id'] )->getData ();
					$seats_available = $bus_type_arr ['seats_count'];
					$seat_booked_arr = $pjBookingSeatModel->reset ()->select ( "DISTINCT t1.seat_id" )->where ( "t1.start_location_id IN(" . join ( ",", $temp_location_id_arr ) . ")
								AND t1.booking_id IN(SELECT TB.id
													FROM `" . $pjBookingModel->getTable () . "` AS TB
													WHERE (TB.status='confirmed'
															OR (TB.status='pending' AND UNIX_TIMESTAMP(TB.created) >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL " . $this->option_arr ['o_min_hour'] . " MINUTE))))
						AND TB.bus_id = $bus_id $and_where)" )->findAll ()->getDataPair ( "seat_id", "seat_id" );
					
					$cnt_booked = count ( $seat_booked_arr );
					$seats_available -= $cnt_booked;
					$bus_arr [$k] ['seats_available'] = $seats_available;
				}
				if (count ( $ticket_arr ) > $ticket_columns) {
					$ticket_columns = count ( $ticket_arr );
				}
				$bus_arr [$k] ['ticket_arr'] = $ticket_arr;
				if ($is_return == 'F') {
					$return_ticket_arr = $pjPriceModel
							->reset()
							->join('pjTicket', 't1.ticket_id = t2.id', 'left')
							->join('pjMultiLang', "t3.model='pjTicket' AND t3.foreign_id=t1.ticket_id AND t3.field='title' AND t3.locale='".$locale_id."'", 'left outer')
							->join('pjBus', 't1.bus_id = t4.id', 'left')
							->select("t1.*, t2.seats_count, t3.content as ticket, t4.discount")
							->where('t1.bus_id', $bus_id)
							->where('t1.from_location_id', $pickup_id)
							->where('t1.to_location_id', $return_id)
							->where('is_return = "T"')
							->index("FORCE KEY (`ticket_id`)")
							->orderBy("ticket ASC")
							->findAll()
							->getData();
					$bus_arr [$k] ['return_ticket_arr'] = $return_ticket_arr;
				}
			}
			
			$seats = $pjSeatModel->reset ()->where ( 't1.bus_type_id', $bus ['bus_type_id'] )->findAll ()->getData ();
			foreach ( $seats as $v ) {
				if (! in_array ( $v ['id'], $seat_booked_arr )) {
					$seat_avail_arr [] = $v ['id'] . '#' . $v ['name'];
				}
			}
			
			$bus_arr [$k] ['seat_avail_arr'] = $seat_avail_arr;
			$bus_arr [$k] ['departure_time'] = $departure_time;
			$bus_arr [$k] ['arrival_time'] = $arrival_time;
			$bus_arr [$k] ['duration'] = $duration;
		}
		
		$bus_type_arr = array ();
		$booked_seat_arr = array ();
		$seat_arr = array ();
		$selected_seat_arr = array ();
		
		if (! empty ( $booked_data ) && ! empty ( $location_id_arr )) {
			$bus_id = ($is_return == 'F' ? $booked_data ['bus_id'] : $booked_data ['return_bus_id']);
			
			$arr = pjBusModel::factory ()->find ( $bus_id )->getData ();
			$bus_type_arr = $pjBusTypeModel->reset ()->find ( $arr ['bus_type_id'] )->getData ();
			
			$booked_seat_arr = $pjBookingSeatModel->reset ()->select ( "DISTINCT seat_id" )->where ( "t1.booking_id IN(SELECT TB.id
										FROM `" . pjBookingModel::factory ()->getTable () . "` AS TB
										WHERE (TB.status='confirmed' OR (TB.status='pending' AND UNIX_TIMESTAMP(TB.created) >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL " . $this->option_arr ['o_min_hour'] . " MINUTE))))
				AND TB.bus_id = $bus_id
				AND TB.booking_date = '$booking_date')
				AND start_location_id IN(" . join ( ",", $location_id_arr ) . ")" )->index ( "FORCE KEY (`booking_id`)" )->findAll ()->getDataPair ( "seat_id", "seat_id" );
			
			$selected_seats_str = ($is_return == 'F' ? $booked_data ['selected_seats'] : $booked_data ['return_selected_seats']);
			$seat_arr = $pjSeatModel->reset ()->where ( 'bus_type_id', $arr ['bus_type_id'] )->findAll ()->getData ();
			$selected_seat_arr = $pjSeatModel->reset ()->whereIn ( 't1.id', explode ( "|", $selected_seats_str ) )->findAll ()->getDataPair ( 'id', 'name' );
		}
		
		$from_location = $pickup_location ['name'];
		$to_location = $return_location ['name'];
		
		return compact ( 'booking_period', 'bus_arr', 'bus_type_arr', 'booked_seat_arr', 'seat_arr', 'selected_seat_arr', 'ticket_columns', 'from_location', 'to_location' );
	}
	
	
	public function getBackupInfo()
	{
		$data = $id = $created = $type = array();
		if ($handle = opendir(PJ_WEB_PATH . 'backup'))
		{
			$i = 0;
			while (false !== ($entry = readdir($handle)))
			{
				preg_match('/(database-backup|files-backup)-(\d{10})\.(sql|zip)/', $entry, $m);
				if (isset($m[2]))
				{
					$id[$i] = $entry;
					$created[$i] = date($this->option_arr['o_date_format'] . ", H:i", $m[2]);
					$type[$i] = $m[1] == 'database-backup' ? 'database' : 'files';
					
					$data[$i]['id'] = $id[$i];
					$data[$i]['created'] = $created[$i];
					$data[$i]['type'] = $type[$i];
					$i++;
				}
			}
			closedir($handle);
		}
		array_multisort($created, SORT_DESC, $id, SORT_DESC, $type, SORT_ASC, $data);
		$total = count($data);
		$rowCount = 1;
		$pages = ceil($total / $rowCount);
		$page = 1;
		if ($page > $pages)
		{
			$page = $pages;
		}
					
		return compact('data', 'total', 'pages', 'page', 'rowCount');
	}
	
	protected function loadSetFields($force=FALSE, $locale_id=NULL, $fields=NULL)
	{
		if (is_null($locale_id))
		{
			$locale_id = $this->getLocaleId();
		}
	
		if (is_null($fields))
		{
			$fields = $this->defaultFields;
		}
	
		$registry = pjRegistry::getInstance();
		if ($force
				|| !isset($_SESSION[$this->defaultFieldsIndex])
				|| $_SESSION[$this->defaultFieldsIndex] != $this->option_arr['o_fields_index']
				|| !isset($_SESSION[$fields])
				|| empty($_SESSION[$fields]))
		{
			pjAppController::setFields($locale_id);
	
			# Update session
			if ($registry->is('fields'))
			{
				$_SESSION[$fields] = $registry->get('fields');
			}
			$_SESSION[$this->defaultFieldsIndex] = $this->option_arr['o_fields_index'];
		}
	
		if (isset($_SESSION[$fields]) && !empty($_SESSION[$fields]))
		{
			# Load fields from session
			$registry->set('fields', $_SESSION[$fields]);
		}
	
		return TRUE;
	}
	
	public function getDiscount($data, $option_arr)
	{
		$resp = array();
		
		if (isset($data['voucher_code']) && !empty($data['voucher_code']))
		{
			$_arr = pjVoucherModel::factory()
				->where('code', $data['voucher_code'])
				->findAll()
				->getData();
			if(count($_arr) > 0)
			{
				$arr = $_arr[0];
				$dt = time();
				if (isset($data['voucher_processed_on']) && !empty($data['voucher_processed_on'])) {
					$dt = strtotime($data['voucher_processed_on']);
				}
				
				$valid = false;
				
				switch ($arr['valid'])
				{
					case 'fixed':
					case 'period':
						$t_from = strtotime($arr['date_from'] . " " . $arr['time_from']);
						$t_to = strtotime($arr['date_to'] . " " . $arr['time_to']);
						if ($t_from <= $dt && $t_to >= $dt)
						{
							$valid = true;
						}
						break;
					case 'recurring':
						$date = date('Y-m-d', $dt);
						$t_from = strtotime($date . " " . $arr['time_from']);
						$t_to = strtotime($date . " " . $arr['time_to']);
						if ($arr['every'] == strtolower(date("l", $dt)) && $t_from <= $dt && $t_to >= $dt)
						{
							$valid = true;
						}
						break;
				}
				if ($valid)
				{
					$resp['voucher_code'] = $arr['code'];
					$resp['voucher_type'] = $arr['type'];
					$resp['voucher_discount'] = $arr['discount'];
					$resp['code'] = 200;
				}else{
					$resp['code'] = 102;
				}
					
			}else{
				$resp['code'] = 101;
			}
		}else {
			$resp['code'] = 100;
		}
		
		return $resp;
	}
	
}
?>