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

	/**
	 * Generate (or return existing) CSRF token for the current session.
	 */
	public static function getCsrfToken()
	{
		if (empty($_SESSION['csrf_token']))
		{
			$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
		}
		return $_SESSION['csrf_token'];
	}

	/**
	 * Validate CSRF token (admin requests).
	 */
	public static function validateCsrfToken()
	{
		$token = '';
		if (!empty($_POST['csrf_token'])) {
			$token = $_POST['csrf_token'];
		} elseif (!empty($_GET['csrf_token'])) {
			$token = $_GET['csrf_token'];
		} elseif (!empty($_SERVER['HTTP_X_CSRF_TOKEN'])) {
			$token = $_SERVER['HTTP_X_CSRF_TOKEN'];
		}
		if (empty($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], (string) $token))
		{
			header('HTTP/1.1 403 Forbidden');
			exit('Invalid CSRF token.');
		}
	}
	
	public $option_arr = array();
	
	public $defaultLocale = 'admin_locale_id';
  
	public $defaultFields = 'fields';
	
	public $defaultFieldsIndex = 'fields_index';
  
	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 isCountryReady()
    {
    	return $this->isAdmin();
    }
    
	public function isOneAdminReady()
    {
    	return $this->isAdmin();
    }
    public function isInvoiceReady()
    {
    	return $this->isAdmin() || $this->isEditor();
    }
	
	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 beforeFilter()
    {
		if (strtoupper(@$_SERVER['REQUEST_METHOD']) === 'POST')
		{
			$_csrf_ctrl = isset($_GET['controller']) ? $_GET['controller'] : '';
			$_csrf_act = isset($_GET['action']) ? $_GET['action'] : '';
			if (strpos($_csrf_ctrl, 'pjAdmin') === 0
				&& !in_array($_csrf_act, array('pjActionLogin', 'pjActionForgot', 'pjActionLogout', 'pjActionPreview'), true)) {
				pjAppController::validateCsrfToken();
			}
		}

    	$this->appendJs('jquery.min.js', PJ_THIRD_PARTY_PATH . 'jquery/');
    	$baseDir = defined("PJ_INSTALL_PATH") ? PJ_INSTALL_PATH : null;
    	$dm = new pjDependencyManager($baseDir, PJ_THIRD_PARTY_PATH);
		$dm->load(PJ_CONFIG_PATH . 'dependencies.php')->resolve();
		$this->appendJs('jquery-migrate.min.js', $dm->getPath('jquery_migrate'), FALSE, FALSE);
		$this->appendJs('pjAdminCore.js');
		$this->appendCss('reset.css');
		 
		$this->appendJs('js/jquery-ui.custom.min.js', PJ_THIRD_PARTY_PATH . 'jquery_ui/');
		$this->appendCss('css/smoothness/jquery-ui.min.css', PJ_THIRD_PARTY_PATH . 'jquery_ui/');
				
		$this->appendCss('pj-all.css', PJ_FRAMEWORK_LIBS_PATH . 'pj/css/');
		$this->appendCss('admin.css');
		
    	if ($_GET['controller'] != 'pjInstaller')
		{
			$this->models['Option'] = pjOptionModel::factory();
			$this->option_arr = $this->models['Option']->getPairs($this->getForeignId());
			$this->set('option_arr', $this->option_arr);
			$this->setTime();
			
			if (!isset($_SESSION[$this->defaultLocale]))
			{
				$locale_arr = pjLocaleModel::factory()->where('is_default', 1)->limit(1)->findAll()->getData();
				if (count($locale_arr) === 1)
				{
					$this->setLocaleId($locale_arr[0]['id']);
				}
			}
			$this->loadSetFields();
		}
    }
    
    public function isEditor()
    {
    	return $this->getRoleId() == 2;
    }
    
    public function getForeignId()
    {
    	return 1;
    }
    
    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 setLocaleId($locale_id)
	{
		$_SESSION[$this->defaultLocale] = (int) $locale_id;
	}
	
	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/maps',
							'app/web/upload/tickets',
							'app/web/upload/tickets/tickets',
							'app/web/upload/tickets/pdfs',
							'app/web/upload/tickets/barcodes'
						);
		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 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 calcPrice($event_id, $store, $option_arr, $locale_id)
	{
		$subtotal = 0;
		$tax = 0;
		$total = 0;
		$deposit = 0;
		
		$discount_store = isset($store['discount_data']) ? $store['discount_data'] : array();
		$ticket_donation = isset($store['tickets']) && isset($store['tickets']['donation']) ? $store['tickets']['donation'] : array();
		$ticket_store = isset($store['tickets']) && isset($store['tickets']['ticket_id']) ? $store['tickets']['ticket_id'] : array();
		$seat_store = isset($store['seats']) && isset($store['seats']['seat_id']) ? $store['seats']['seat_id'] : array();
		
		$temp_discount_arr = isset($discount_store['ticket_id_arr']) && !empty($discount_store['ticket_id_arr']) ? explode("~|~", $discount_store['ticket_id_arr']) : array();
		$discount_arr = array();
		foreach($temp_discount_arr as $k => $price_str)
		{
			list($ticket_id, $price, $price_format) = explode("~:~", $price_str);
			$discount_arr[$ticket_id] = compact('price', 'price_format');
		}
		$discount_count = isset($discount_store['count']) ? $discount_store['count'] : -1;
		
		$ticket_id_arr = array();
		foreach($ticket_store as $ticket_id => $qty)
		{
			if($qty > 0)
			{
				$ticket_id_arr[] = $ticket_id;
			}
		}
		
		$ticket_arr = array();
		$seat_arr = array();
		
		if(!empty($ticket_id_arr))
		{
			$temp_ticket_arr = pjTicketModel::factory()
				->select(sprintf("t1.*, t2.content as title") )
				->join('pjMultiLang', "t2.model='pjTicket' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='".$locale_id."'", 'left outer')
				->where('event_id', $event_id)
				->whereIn('t1.id', $ticket_id_arr)
				->orderBy('sale_start ASC')
				->findAll()
				->getData();
			
			$temp_seat_arr = pjSeatTicketModel::factory()
				->select("t1.*, t2.name")
				->join("pjSeat", "t1.seat_id=t2.id", 'left')
				->where('t2.event_id', $event_id)
				->whereIn("t1.ticket_id", $ticket_id_arr)
				->findAll()
				->getData();
			
			foreach($temp_ticket_arr as $k => $v)
			{
				$ticket_arr[$v['id']] = $v;
			}
			
			foreach($ticket_store as $ticket_id => $qty)
			{
				if($qty > 0)
				{
					$ticket_price = 0;
					$ticket_arr[$ticket_id]['donation'] = NULL; 
					if(isset($ticket_arr[$ticket_id]))
					{
						if($ticket_arr[$ticket_id]['type'] == 'paid')
						{
							if($discount_count > 0 && $qty >= $discount_count && isset($discount_arr[$ticket_id]))
							{
								$ticket_price = $qty * (float) $discount_arr[$ticket_id]['price'];
								$ticket_arr[$ticket_id]['unit_price'] = (float) $discount_arr[$ticket_id]['price'];
							}else{
								$ticket_price = $qty * (float) $ticket_arr[$ticket_id]['price'];
								$ticket_arr[$ticket_id]['unit_price'] = (float) $ticket_arr[$ticket_id]['price'];
							}
							
						}else if($ticket_arr[$ticket_id]['type'] == 'donation'){
							if(isset($ticket_donation[$ticket_id]))
							{
								$ticket_price = $qty * (float) $ticket_donation[$ticket_id];
								$ticket_arr[$ticket_id]['donation'] = (float) $ticket_donation[$ticket_id];
							}
						}
					}
					$subtotal += $ticket_price;
					$ticket_arr[$ticket_id]['qty'] = $qty;
					$ticket_arr[$ticket_id]['total'] = $ticket_price;
				}
			}
			foreach($temp_seat_arr as $k => $v)
			{
				if(isset($seat_store[$v['ticket_id']][$v['seat_id']]))
				{
					$seat_arr[$v['ticket_id']][] = $v;
				}
			}
		}
		
		$tax = $subtotal * $option_arr['o_tax_payment'] / 100;
		$total = $subtotal + $tax;
		$deposit = $total * $option_arr['o_deposit_payment'] / 100;
		
		return compact('ticket_arr', 'seat_arr', 'subtotal', 'tax', 'total', 'deposit');
	}
	
	public function getAdminEmail()
	{
		$arr = pjUserModel::factory()
			->findAll()
			->orderBy("t1.id ASC")
			->limit(1)
			->getData();
		return !empty($arr) ? $arr[0]['email'] : null;	
	}
	
	public function getAdminPhone()
	{
		$arr = pjUserModel::factory()
			->findAll()
			->orderBy("t1.id ASC")
			->limit(1)
			->getData();
		return !empty($arr) ? (!empty($arr[0]['phone']) ? $arr[0]['phone'] : null) : null;	
	}
	
	public function getTokens($option_arr, $booking_arr, $salt, $locale_id)
	{
		$personal_titles = __('personal_titles', true, false);
		$cancelURL = PJ_INSTALL_URL . 'index.php?controller=pjFront&action=pjActionCancel&id='.@$booking_arr['id'].'&hash='.sha1(@$booking_arr['id'].@$booking_arr['created'].$salt);
		$cancelURL = '<a href="'.$cancelURL.'">'.$cancelURL.'</a>';
		
		$PDFticket = '';
		if(is_file(PJ_INSTALL_PATH . PJ_UPLOAD_PATH . 'tickets/pdfs/p_' . $booking_arr['uuid'] . '.pdf'))
		{
			$PDFticket = PJ_INSTALL_URL . PJ_UPLOAD_PATH . 'tickets/pdfs/p_' . $booking_arr['uuid'] . '.pdf';
			$PDFticket = '<a href="'.$PDFticket.'">'.$PDFticket.'</a>';
		}
	
		$payment_methods = __('payment_methods', true, false);
		
		$seat_arr = array();
		if(isset($booking_arr['seats']) && !empty($booking_arr['map']))
		{
			foreach($booking_arr['seats'] as $k => $v)
			{
				$seat_arr[$v['ticket_id']][] = $v['seat_name'];
			}
		}
		
		$tickets = null;
		$ticket_arr = array();
		if(isset($booking_arr['tickets']))
		{
			foreach($booking_arr['tickets'] as $ticket_id => $seat_arr)
			{
				if(count($seat_arr) > 0)
				{
					$ticket = $seat_arr[0];
					if($ticket['ticket_type'] == 'paid')
					{
						$ticket_arr[] = $ticket['ticket'] . ' (' . pjUtil::formatCurrencySign($ticket['unit_price'], $option_arr['o_currency']) . ') x ' . count($seat_arr);
					} else if($ticket['ticket_type'] == 'donation'){
						$ticket_arr[] = $ticket['ticket'] . ' (' . pjUtil::formatCurrencySign($ticket['donation'], $option_arr['o_currency']) . ') x ' . count($seat_arr);
					} else {
						$ticket_arr[] = $ticket['ticket'] . ' (' . __('lblFree', true) . ') x ' . count($seat_arr);
					}
					if(!empty($booking_arr['map']))
					{
						$temp_seat_arr = array();
						foreach($seat_arr as $k => $v )
						{
							$temp_seat_arr[] = $v['seat_name'];
						}
						$ticket_arr[] = __('lblSeats', true) . ': ' . implode(" | ", $temp_seat_arr);
					}
				} 
			}
		}
		$tickets = implode("<br/>", $ticket_arr);
		
		$cc_exp = @$booking_arr['cc_exp_month'] . '/' . @$booking_arr['cc_exp_year'];
		
		$event_date = null;
		if(isset($booking_arr['event_id']) && (int) $booking_arr['event_id'] > 0)
		{
			$event_arr = pjEventModel::factory()->find($booking_arr['event_id'])->getData();
			$event_date = date($option_arr['o_date_format'], strtotime($event_arr['start_date']));
		}
		
		$search = array(
				'{Title}',
				'{Name}',
				'{Email}',
				'{Phone}',
				'{Company}',
				'{Address}',
				'{City}',
				'{State}',
				'{Zip}',
				'{Country}',
				'{Notes}',
				'{BookingID}',
				'{Event}',
				'{EventDate}',
				'{Tickets}',
				'{BookingID}',
				'{SubTotal}',
				'{Tax}',
				'{Total}',
				'{Deposit}',
				'{PaymentMethod}',
				'{CCType}',
				'{CCNum}',
				'{CCExp}',
				'{CCSec}',
				'{CancelURL}',
				'{PDFTicket}'
	
		);
		$replace = array(
				(!empty($booking_arr['c_title']) ? $personal_titles[$booking_arr['c_title']] : null),
				$booking_arr['c_name'],
				$booking_arr['c_email'],
				$booking_arr['c_phone'],
				$booking_arr['c_company'],
				$booking_arr['c_address'],
				$booking_arr['c_city'],
				$booking_arr['c_state'],
				$booking_arr['c_zip'],
				$booking_arr['country_title'],
				$booking_arr['c_notes'],
				$booking_arr['uuid'],
				$booking_arr['event_title'],
				$event_date,
				$tickets,
				$booking_arr['uuid'],
				pjUtil::formatCurrencySign($booking_arr['sub_total'], $option_arr['o_currency']),
				pjUtil::formatCurrencySign($booking_arr['tax'], $option_arr['o_currency']),
				pjUtil::formatCurrencySign($booking_arr['total'], $option_arr['o_currency']),
				pjUtil::formatCurrencySign($booking_arr['deposit'], $option_arr['o_currency']),
				@$payment_methods[$booking_arr['payment_method']],
				@$booking_arr['cc_type'],
				@$booking_arr['cc_num'],
				(@$booking_arr['payment_method'] == 'creditcard' ? $cc_exp : NULL),
				@$booking_arr['cc_code'],
				$cancelURL,
				$PDFticket
		);
	
		return compact('search', 'replace');
	}
	
	public function pjActionGenerateInvoice($arr)
	{
		$map = array(
				'confirmed' => 'paid',
				'cancelled' => 'cancelled',
				'pending' => 'not_paid'
		);
	
		$response = $this->requestAction(
				array(
						'controller' => 'pjInvoice',
						'action' => 'pjActionCreate',
						'params' => array(
								'key' => md5($this->option_arr['private_key'] . PJ_SALT),
								
								'uuid' => pjInvoiceModel::factory()->getInvoiceID(),
								'order_id' => $arr['uuid'],
								'foreign_id' => 1,
								'issue_date' => ':CURDATE()',
								'due_date' => ':CURDATE()',
								'created' => ':NOW()',
								'status' => @$map[$arr['status']],
								'payment_method' => $arr['payment_method'],
								'cc_type' => $arr['cc_type'],
								'cc_num' => $arr['cc_num'],
								'cc_exp_month' => $arr['cc_exp_month'],
								'cc_exp_year' => $arr['cc_exp_year'],
								'cc_code' => $arr['cc_code'],
								'subtotal' => $arr['sub_total'],
								'tax' => $arr['tax'],
								'total' => $arr['total'],
								'paid_deposit' => $arr['deposit'],
								'amount_due' => $arr['total'] - $arr['deposit'],
								'currency' => $this->option_arr['o_currency'],
								'notes' => $arr['c_notes'],
								
								'b_billing_address' => $arr['c_address'],
								
								'b_name' => $arr['c_name'],
								'b_address' => $arr['c_address'],
								'b_street_address' => $arr['c_address'],
								'b_company' => $arr['c_company'],
								'b_city' => $arr['c_city'],
								'b_state' => $arr['c_state'],
								'b_zip' => $arr['c_zip'],
								'b_phone' => $arr['c_phone'],
								
								'b_email' => $arr['c_email'],
								
								'items' => array(
										array(
												'name' => $arr['event_title'],
												'description' => $arr['tickets'],
												'qty' => 1,
												'unit_price' => $arr['total'],
												'amount' => $arr['total']
										)
								)
						)
				),
				array('return')
		);
	
		return $response;
	}
	
	public function pjActionGetBookingDetails($id)
	{
		$arr = pjBookingModel::factory()
			->join('pjMultiLang', "t2.model='pjEvent' AND t2.foreign_id=t1.event_id AND t2.field='title' AND t2.locale='".$this->getLocaleId()."'", 'left outer')
			->join('pjMultiLang', "t3.model='pjCountry' AND t3.foreign_id=t1.c_country AND t3.field='name' AND t3.locale='".$this->getLocaleId()."'", 'left outer')
			->join('pjEvent', "t4.id=t1.event_id", 'left outer')
			->join('pjMultiLang', "t5.model='pjEvent' AND t5.foreign_id=t1.event_id AND t5.field='ticket_data' AND t5.locale='".$this->getLocaleId()."'", 'left outer')
			->select(sprintf("t1.*,
					AES_DECRYPT(t1.cc_type, '%1\$s') AS `cc_type`,	
					AES_DECRYPT(t1.cc_num, '%1\$s') AS `cc_num`,
					AES_DECRYPT(t1.cc_exp_month, '%1\$s') AS `cc_exp_month`,
					AES_DECRYPT(t1.cc_exp_year, '%1\$s') AS `cc_exp_year`,
					AES_DECRYPT(t1.cc_code, '%1\$s') AS `cc_code`, 
					t2.content as event_title, t3.content as country_title, t4.map, t4.ticket_img, t4.start_date, t5.content as ticket_data",PJ_SALT))
			->find($id)
			->getData();
	
		$temp_bt_arr = pjBookingTicketModel::factory()
			->select("t1.*, t2.content as ticket, t3.type as ticket_type, t3.price, t4.name as seat_name")
			->join('pjMultiLang', "t2.model='pjTicket' AND t2.foreign_id=t1.ticket_id AND t2.field='title' AND t2.locale='".$this->getLocaleId()."'", 'left outer')
			->join('pjTicket', "t1.ticket_id=t3.id", 'left outer')
			->join('pjSeat', "t1.seat_id=t4.id", 'left outer')
			->where("booking_id", $id)
			->findAll()
			->getData();
		
		$bt_arr = array();
		foreach($temp_bt_arr as $k => $v)
		{
			$bt_arr[$v['ticket_id']][] = $v;
		}
		
		$arr['tickets'] = $bt_arr;
	
		return $arr;
	}
	
	public function buildPdfTickets($arr)
	{
		
		if(!empty($arr['ticket_img']) && is_file($arr['ticket_img']) && !empty($arr['ticket_data']))
		{
			$ticket_template = $arr['ticket_data'];
			
			$tickets = null;
			$ticket_arr = array();
			if(isset($arr['tickets']))
			{
				foreach($arr['tickets'] as $ticket_id => $seat_arr)
				{
					if(count($seat_arr) > 0)
					{
						$ticket = $seat_arr[0];
						foreach($seat_arr as $k => $v)
						{
							$temp_ticket = array();
							$temp_ticket['seat'] = '';
							if(!empty($arr['map']))
							{
								$temp_ticket['seat'] = $v['seat_name'];
							}
							$temp_ticket['ticket_id'] = $v['ticket_code'];
							$temp_ticket['uuid'] = $arr['uuid'];
							$temp_ticket['name'] = $v['attendee_name'];
							$temp_ticket['email'] = $arr['c_email'];
							$temp_ticket['phone'] = $arr['c_phone'];
							$temp_ticket['event'] = $arr['event_title'];
							$temp_ticket['event_date'] = $arr['start_date'];
							if($ticket['ticket_type'] == 'paid')
							{
								$temp_ticket['ticket'] = $ticket['ticket'] . ' (' . pjUtil::formatCurrencySign($ticket['unit_price'], $this->option_arr['o_currency']) . ')';
							} else if($ticket['ticket_type'] == 'donation'){
								$temp_ticket['ticket'] =$ticket['ticket'] . ' (' . pjUtil::formatCurrencySign($ticket['donation'], $this->option_arr['o_currency']) . ')';
							} else {
								$temp_ticket['ticket'] = $ticket['ticket'] . ' (' . __('lblFree', true) . ')';
							}
							
							$temp_ticket['ticket_img'] = $arr['ticket_img'];
							$tokens = pjAppController::getTicketTokens($this->option_arr, $temp_ticket, PJ_SALT, $this->getLocaleId());
								
							$ticket_info = str_replace($tokens['search'], $tokens['replace'], $ticket_template);
							$ticket_info = preg_replace('/\r\n|\n/', '<br />', $ticket_info);
							$temp_ticket['ticket_info'] = $ticket_info;
								
							$ticket_arr[] = $temp_ticket;
						}
					}
				}
				
				$pjTicketPdf = new pjTicketPdf();
				$pjTicketPdf->generatePdf($ticket_arr);
			}
			
		}
	}
	
	public function getTicketTokens($option_arr, $ticket, $salt, $locale_id)
	{
		$event_date = null;
		if(!empty($ticket['event_date']))
		{
			$event_date = date($option_arr['o_date_format'], strtotime($ticket['event_date']));
		}
		$search = array(
				'{Name}',
				'{Email}',
				'{Phone}',
				'{Event}',
				'{EventDate}',
				'{Ticket}',
				'{Seat}'
	
		);
		$replace = array(
				$ticket['name'],
				$ticket['email'],
				$ticket['phone'],
				$ticket['event'],
		        $event_date,
				$ticket['ticket'],
				$ticket['seat']
	
		);
		return compact('search', 'replace');
	}
	
	public function deletePDFTickets($booking_id, $uuid)
	{
		$ticket_arr = pjBookingTicketModel::factory()->where('booking_id', $booking_id)->findAll()->getData();
		foreach($ticket_arr as $k => $v)
		{
			$barcode_path = PJ_INSTALL_PATH . PJ_UPLOAD_PATH . 'tickets/barcodes/b_'. $uuid . '-' . $v['ticket_id'] . '-' . ($k + 1)  .'.png';
			$ticket_path = PJ_INSTALL_PATH . PJ_UPLOAD_PATH . 'tickets/tickets/t_' . $uuid . '-' . $v['ticket_id'] . '-' . ($k + 1)  .'.png';
			if(is_file($barcode_path))
			{
				@unlink($barcode_path);
			}
			if(is_file($ticket_path))
			{
				@unlink($ticket_path);
			}
		}
		$pdf_path = PJ_INSTALL_PATH . PJ_UPLOAD_PATH . 'tickets/pdfs/p_'. $uuid . '.pdf';
		if(is_file($pdf_path))
		{
			@unlink($pdf_path);
		}
	}
	
	public function finalCheck($event_id, $data, $source, $is_updated)
	{
		$result = array();
		$result['status'] = 'OK';
		$result['code'] = '200';
		
		$event_arr = pjEventModel::factory()
			->select(sprintf("t1.*,
								(SELECT COUNT(`TBT`.ticket_id) FROM `%1\$s` AS `TBT` WHERE `TBT`.booking_id IN (SELECT `TB`.id FROM `%2\$s` AS `TB` WHERE `TB`.event_id=t1.id AND (`TB`.status='confirmed' OR `TB`.status='pending' )) ) AS tickets_sold,
								(SELECT SUM(`TT2`.available_tickets) FROM `%3\$s` AS `TT2` WHERE `TT2`.event_id=t1.id) AS cnt_tickets
							",pjBookingTicketModel::factory()->getTable(),
				pjBookingModel::factory()->getTable(),
				pjTicketModel::factory()->getTable()))
			->find($event_id)
			->getData();
		
		$available = (int) $event_arr['cnt_tickets'] - (int) $event_arr['tickets_sold'];
		$has_map = !empty($event_arr['map']) ? true : false;
		
		if($source == 'front')
		{
			$price_arr = $data;
			if(isset($price_arr['ticket_arr']))
			{
				$total_qty = 0;
				$ticket_id_arr = array();
				foreach($price_arr['ticket_arr'] as $k => $ticket)
				{
					$total_qty += (int) $ticket['qty'];
					$ticket_id_arr[] = $ticket['id'];
				}
				
				if(!empty($ticket_id_arr))
				{
					if($total_qty > $available)
					{
						$result['status'] = 'ERR';
						$result['code'] = '100';
					}else{
						if($has_map == true)
						{
							$booked_seat_arr = pjBookingTicketModel::factory()
								->select("t1.*")
								->where(sprintf("(t1.booking_id IN (SELECT `TB`.id FROM `%1\$s` AS `TB` WHERE `TB`.event_id='%2\$s' AND (`TB`.status='confirmed' OR `TB`.status='pending') ) )", pjBookingModel::factory()->getTable(), $event_id))
								->findAll()
								->getDataPair(null, 'seat_id');
							foreach($price_arr['ticket_arr'] as $k => $ticket)
							{
								if(isset($price_arr['seat_arr']) && isset($price_arr['seat_arr'][$ticket['id']]))
								{
									foreach($price_arr['seat_arr'][$ticket['id']] as $key => $seat)
									{
										if(in_array($seat['seat_id'], $booked_seat_arr))
										{
											$result['status'] = 'ERR';
											$result['code'] = '101';
											break;
										}
									}
								}
							}
						}
					}
				}
			}
		}else{
			$post = $data;
			if(isset($post['count']) && is_array($post['count']) && count($post['count']))
			{
				$total_qty = 0;
				$ticket_id_arr = array();
				foreach($post['count'] as $ticket_id => $count)
				{
					$total_qty += $count;
					$ticket_id_arr[] = $ticket_id;
				}
				if(!empty($ticket_id_arr))
				{
					if($total_qty > $available)
					{
						$result['status'] = 'ERR';
						$result['code'] = '100';
					}else{
						if($has_map == true)
						{
							$and_where = '';
							if($update_id > 0)
							{
								$and_where .= " AND `TB`.id <> '".$update_id."'";
							}
							$booked_seat_arr = pjBookingTicketModel::factory()
								->select("t1.*")
								->where(sprintf("(t1.booking_id IN (SELECT `TB`.id FROM `%1\$s` AS `TB` WHERE `TB`.event_id='%2\$s' AND (`TB`.status='confirmed' OR `TB`.status='pending') ) )", pjBookingModel::factory()->getTable(), $event_id))
								->findAll()
								->getDataPair(null, 'seat_id');
							
							foreach($post['count'] as $ticket_id => $count)
							{
								if(isset($post['seat_id'][$ticket_id]) && is_array($post['seat_id'][$ticket_id]) && count($post['seat_id'][$ticket_id]))
								{
									foreach($post['seat_id'][$ticket_id] as $key => $seat_id)
									{
										if(in_array($seat_id, $booked_seat_arr))
										{
											$result['status'] = 'ERR';
											$result['code'] = '101';
											break;
										}
									}
								}
							}
						}
					}
				}
			}
		}
		return $result;
	}
}
?>