<?php
if (!defined("ROOT_PATH"))
{
	header("HTTP/1.1 403 Forbidden");
	exit;
}
class pjAppController extends pjBaseAppController
{
	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. pjInput nulls raw $_POST/$_GET, so read request objects first.
	 */
	public static function validateCsrfToken()
	{
		$token = '';
		$reg = pjRegistry::getInstance();
		$post = $reg->get('_post');
		$get = $reg->get('_get');
		if (is_object($post) && $post->check('csrf_token')) {
			$token = (string) $post->toString('csrf_token');
		} elseif (is_object($get) && $get->check('csrf_token')) {
			$token = (string) $get->toString('csrf_token');
		} elseif (!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 $defaultCalendarId = 'admin_calendar_id';
	
	public $defaultSlots = 'TSBC_Slots';
	
	private $layoutRange = array(1, 2);
	
	public function pjActionCheckInstall()
	{
	    $this->setLayout('pjActionEmpty');
	    
	    $result = array('status' => 'OK', 'code' => 200, 'text' => 'Operation succeeded', 'info' => array());
	    $folders = array('app/web/upload');
	    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 getLayoutRange()
	{
		return $this->layoutRange;
	}
	
	public function beforeFilter()
	{
	    parent::beforeFilter();
	    
	    if(!in_array($this->_get->toString('controller'), array('pjFront', 'pjInstaller')))
	    {
	        $pjCalendarModel = pjCalendarModel::factory();
	        if(!$this->isMasterAdmin())
	        {
	            $pjCalendarModel->where(sprintf("(t1.id IN(SELECT `TCU`.calendar_id FROM `%s` AS `TCU` WHERE `TCU`.user_id=%u))", pjCalendarUserModel::factory()->getTable(), $this->getUserId()));
	        }
	        $calendar_id_arr = $pjCalendarModel->findAll()->getDataPair(NULL, 'id');
	        if(!$this->getCalendarId())
	        {
	            if (count($calendar_id_arr) >= 1)
	            {
	                $this->setCalendarId($calendar_id_arr[0]);
	            }
	        }else{
	            if(!in_array($this->getCalendarId(), $calendar_id_arr) && !$this->isMasterAdmin())
	            {
	                $this->setCalendarId($calendar_id_arr[0]);
	            }
	        }
	        
	        $pjCalendarModel = pjCalendarModel::factory();
	        if(!$this->isMasterAdmin())
	        {
	            $pjCalendarModel->where(sprintf("(t1.id IN(SELECT `TCU`.calendar_id FROM `%s` AS `TCU` WHERE `TCU`.user_id=%u))", pjCalendarUserModel::factory()->getTable(), $this->getUserId()));
	        }
	        $calendar_arr = $pjCalendarModel
	        ->select("t1.*, t2.content as title")
	        ->join('pjMultiLang', sprintf("t2.model='pjCalendar' AND t2.foreign_id=t1.id AND t2.field='title' AND t2.locale='%u'", $this->getLocaleId()), 'left outer')
	        ->orderBy("t2.content ASC")
	        ->findAll()->getData();
	        $this->set('calendar_arr', $calendar_arr);
	        
	        $base_option_arr = pjBaseOptionModel::factory()->getPairs(1);
	        $script_option_arr = pjOptionModel::factory()->getPairs($this->getCalendarId());
	        $this->option_arr = array_merge($base_option_arr, $script_option_arr);
	        $this->set('option_arr', $this->option_arr);
	        
	        pjRegistry::getInstance()->set('options', $this->option_arr);
	        
	        $this->appendJs('pjAdminCore.js');
	    }
	    
	    return true;
	}
	public function afterFilter()
	{
	    parent::afterFilter();
	    if(!in_array($this->_get->toString('controller'), array('pjFront', 'pjInstaller')))
	    {
	        $this->appendCss('admin.css');
	    }
	}
    
	public function pjActionAfterInstall()
	{
	    $this->setLayout('pjActionEmpty');
	    
	    $result = array('status' => 'OK', 'code' => 200, 'text' => 'Operation succeeded', 'info' => array());
	    $pjAuthRolePermissionModel = pjAuthRolePermissionModel::factory();
	    $pjAuthUserPermissionModel = pjAuthUserPermissionModel::factory();
	    
	    $permissions = pjAuthPermissionModel::factory()->findAll()->getDataPair('key', 'id');
	    
	    $roles = array(1 => 'admin', 2 => 'editor');
	    foreach ($roles as $role_id => $role)
	    {
	        if (isset($GLOBALS['CONFIG'], $GLOBALS['CONFIG']["role_permissions_{$role}"])
	        && is_array($GLOBALS['CONFIG']["role_permissions_{$role}"])
	        && !empty($GLOBALS['CONFIG']["role_permissions_{$role}"]))
	        {
	            $pjAuthRolePermissionModel->reset()->where('role_id', $role_id)->eraseAll();
	            
	            foreach ($GLOBALS['CONFIG']["role_permissions_{$role}"] as $role_permission)
	            {
	                if($role_permission == '*')
	                {
	                    // Grant full permissions for the role
	                    foreach($permissions as $key => $permission_id)
	                    {
	                        $pjAuthRolePermissionModel->setAttributes(compact('role_id', 'permission_id'))->insert();
	                    }
	                    break;
	                }
	                else
	                {
	                    $hasAsterix = strpos($role_permission, '*') !== false;
	                    if($hasAsterix)
	                    {
	                        $role_permission = str_replace('*', '', $role_permission);
	                    }
	                    
	                    foreach($permissions as $key => $permission_id)
	                    {
	                        if($role_permission == $key || ($hasAsterix && strpos($key, $role_permission) !== false))
	                        {
	                            $pjAuthRolePermissionModel->setAttributes(compact('role_id', 'permission_id'))->insert();
	                        }
	                    }
	                }
	            }
	        }
	    }
	    pjAuthRoleModel::factory()->setAttributes(array('id' => 3, 'role' => 'Client', 'is_backend' => 'F', 'T'))->insert();
	    
	    // Grant full permissions to Admin
	    $user_id = 1; // Admin ID
	    $pjAuthUserPermissionModel->reset()->where('user_id', $user_id)->eraseAll();
	    foreach($permissions as $key => $permission_id)
	    {
	        $pjAuthUserPermissionModel->setAttributes(compact('user_id', 'permission_id'))->insert();
	    }
	    
		$calendar_id = pjCalendarModel::factory()->init(1, 1);
		
		$pjBaseOptionModel = pjBaseOptionModel::factory();
		$base_option_arr = $pjBaseOptionModel->where('foreign_id', 1)->where("(tab_id <> 99 OR (tab_id = 99 AND `key` IN ('plugin_sms_api_key', 'plugin_sms_country_code', 'plugin_sms_phone_number_length', 'private_key', 'o_fields_index')))")->findAll()->getData();
		$pjBaseOptionModel->reset()->setBatchFields(array('foreign_id', 'key', 'tab_id', 'value', 'label', 'type', 'order', 'is_visible', 'style'));
		foreach ($base_option_arr as $record)
		{
		    $record['foreign_id'] = 0;
		    foreach ($record as $k => $v) {
		        if (empty($v)) {
		            $record[$k] = '';
		        }
		    }
		    $pjBaseOptionModel->addBatchRow($record);
		}
		$pjBaseOptionModel->insertBatch();
		
		
		return $result;
	}
	
	/* public function getForeignId()
	{
	    if (isset($_SESSION[$this->defaultCalendarId]))
	    {
	        return $_SESSION[$this->defaultCalendarId];
	    }
	    return 1;
	} */
	
	public function getCalendarId()
	{
	    if (isset($_SESSION[$this->defaultCalendarId]))
	    {
	        return $_SESSION[$this->defaultCalendarId];
	    }
	    return false;
	}
	
	public function setCalendarId($calendar_id)
	{
	    $_SESSION[$this->defaultCalendarId] = (int) $calendar_id;
	    return $this;
	}
	public function isMasterAdmin()
	{
	    return (int) $this->getUserId() === 1;
	}
	public function isEditor()
	{
	    return (int) $this->getRoleId() === 2;
	}
	public function isClient()
	{
	    return $this->getRoleId() == 3;
	}
	
	public function isCountryReady()
	{
	    return $this->isAdmin();
	}
	public function isOneAdminReady()
	{
	    return $this->isAdmin();
	}
	
	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 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 static function getFromEmail()
	{
	    $arr = pjAuthUserModel::factory()
	    ->findAll()
	    ->orderBy("t1.id ASC")
	    ->limit(1)
	    ->getData();
	    return !empty($arr) ? $arr[0]['email'] : null;
	}
	
	public static function getAdminEmail()
	{
	    $arr = pjAuthUserModel::factory()
	    ->where('t1.role_id', '1')
	    ->where('t1.status', 'T')
	    ->limit(1)
	    ->findAll()
	    ->getDataPair('id', 'email');
	    return $arr;
	}
	public static function getAdminPhone()
	{
	    $arr = pjAuthUserModel::factory()
	    ->where('t1.role_id', '1')
	    ->where('t1.status', 'T')
	    ->limit(1)
	    ->findAll()
	    ->getDataPair('id', 'phone');
	    return $arr;
	}
		
	public static function getTokens($booking_arr, $option_arr)
	{
		$timeslots = NULL;
		$tmp = array();
		$hidePrices = (int) $option_arr['o_hide_prices'] === 1;
		if (isset($booking_arr['bs_arr']))
		{
			foreach ($booking_arr['bs_arr'] as $item)
			{
				$tmp[] = sprintf("%s | %s - %s%s",
					pjDateTime::formatDate($item['booking_date'], 'Y-m-d', $option_arr['o_date_format']),
					date($option_arr['o_time_format'], $item['start_ts']),
					date($option_arr['o_time_format'], $item['end_ts']),
				    $hidePrices ? NULL : " | " . (int)$item['cnt'] . " x " .  pjCurrency::formatPrice($item['price'])
				);
			}
		}
		if (!empty($tmp))
		{
			$timeslots = join("\n", $tmp);
		}
		
		$payment_methods = pjObject::getPlugin('pjPayments') !== NULL? pjPayments::getPaymentTitles($booking_arr['calendar_id'], $booking_arr['locale_id']): __('payment_methods',true);
		
		$search = array(
			'{Name}', '{Phone}', '{Email}', '{Notes}', '{Country}', '{CalendarName}', 
			'{State}', '{City}', '{Zip}', '{Address1}', '{Address2}',
		 	'{CCType}', '{CCNum}', '{CCExpMonth}', '{CCExpYear}', '{CCSec}',
		 	'{PaymentMethod}', '{Deposit}', '{Tax}', '{Total}', '{Price}', '{VoucherCode}', '{Discount}',
			'{BookingID}', '{Timeslots}', '{CancelURL}'
		);
		$replace = array(
			@$booking_arr['customer_name'], @$booking_arr['customer_phone'], @$booking_arr['customer_email'], @$booking_arr['customer_notes'], @$booking_arr['country_name'], @$booking_arr['calendar_name'], 
			@$booking_arr['customer_state'], @$booking_arr['customer_city'], @$booking_arr['customer_zip'], @$booking_arr['customer_address_1'], @$booking_arr['customer_address_2'],
			@$booking_arr['cc_type'], @$booking_arr['cc_num'], @$booking_arr['cc_exp_month'], @$booking_arr['cc_exp_year'], @$booking_arr['cc_code'],
			@$payment_methods[$booking_arr['payment_method']],
		    $hidePrices ? NULL : pjCurrency::formatPrice(@$booking_arr['booking_deposit']),
		    $hidePrices ? NULL : pjCurrency::formatPrice(@$booking_arr['booking_tax']),
		    $hidePrices ? NULL : pjCurrency::formatPrice(@$booking_arr['booking_total']),
		    $hidePrices ? NULL : pjCurrency::formatPrice(@$booking_arr['booking_price']),
		    $hidePrices ? NULL : @$booking_arr['discount_code'],
		    $hidePrices ? NULL : pjCurrency::formatPrice(@$booking_arr['booking_discount']),
			@$booking_arr['uuid'], $timeslots, sprintf("%sindex.php?controller=pjFrontEnd&action=pjActionCancel&uuid=%s&hash=%s", PJ_INSTALL_URL, $booking_arr['uuid'], sha1($booking_arr['uuid'] . PJ_SALT))
		);
		
		return compact('search', 'replace');
	}
	
	public static function getClientTokens($option_arr, $client_id, $salt, $locale_id)
	{
	    $country = NULL;
	    $client = pjClientModel::factory()->find($client_id)->getData();
	    $auth_client = pjAuthUserModel::factory()->find($client['foreign_id'])->getData();
	    if(isset($client['customer_country']) && (int) $client['customer_country'] > 0)
	    {
	        $country_arr = pjBaseCountryModel::factory()
	        ->select('t1.id, t2.content AS country_title')
	        ->join('pjBaseMultiLang', "t2.model='pjBaseCountry' AND t2.foreign_id=t1.id AND t2.field='name' AND t2.locale='".$locale_id."'", 'left outer')
	        ->find($client['customer_country'])->getData();
	        if (!empty($country_arr))
	        {
	            $country = $country_arr['country_title'];
	        }
	    }
	    $search = array(
	        '{Title}', '{Name}', '{Phone}', '{Email}', '{Password}',
	        '{Notes}', '{Address1}', '{Address2}', '{City}', '{State}', '{Zip}', '{Country}');
	    $replace = array(
	        @$client['c_title'], pjSanitize::clean(@$auth_client['name']), pjSanitize::clean(@$auth_client['phone']), pjSanitize::clean(@$auth_client['email']), @$auth_client['password'],
	        @$client['customer_notes'], pjSanitize::clean(@$client['customer_address_1']), pjSanitize::clean(@$client['customer_address_2']), pjSanitize::clean(@$client['customer_city']), pjSanitize::clean(@$client['customer_state']), pjSanitize::clean(@$client['customer_zip']), $country);
	    return compact('search', 'replace');
	}
	
	public static function pjActionGetSubjectMessage($notification, $locale_id, $calendar_id)
	{
	    $field = $notification['variant'] . '_tokens_' . $notification['recipient'];
	    $field = str_replace('confirmation', 'confirm', $field);
	    $pjMultiLangModel = pjMultiLangModel::factory();
	    $lang_message = $pjMultiLangModel
	    ->reset()
	    ->select('t1.*')
	    ->where('t1.foreign_id', $calendar_id)
	    ->where('t1.model','pjCalendar')
	    ->where('t1.locale', $locale_id)
	    ->where('t1.field', $field)
	    ->limit(0, 1)
	    ->findAll()
	    ->getData();
	    $field = $notification['variant'] . '_subject_' . $notification['recipient'];
	    $field = str_replace('confirmation', 'confirm', $field);
	    $lang_subject = $pjMultiLangModel
	    ->reset()
	    ->select('t1.*')
	    ->where('t1.foreign_id',  $calendar_id)
	    ->where('t1.model','pjCalendar')
	    ->where('t1.locale', $locale_id)
	    ->where('t1.field', $field)
	    ->limit(0, 1)
	    ->findAll()
	    ->getData();
	    return compact('lang_message', 'lang_subject');
	}
	
	public static function getPrices($calendar_id, $wt_arr, $date, $start_ts, $end_ts, $qty)
	{
		$price = 0;
		
		$date_arr = pjDateModel::factory()->getDailyWorkingTime($calendar_id, $date);
		
		if ($date_arr !== false && $date_arr['is_dayoff'] == 'F')
		{
		    $price = (float) $date_arr['price'] * $qty;
		    $price_arr = pjPriceModel::factory()
		    ->where('t1.calendar_id', $calendar_id)
		    ->where('t1.date', $date)
		    ->where('t1.start_ts', $start_ts)
		    ->where('t1.end_ts', $end_ts)
		    ->orderBy('t1.start_time ASC')
		    ->limit(1)
		    ->findAll()
		    ->getData();
		    if (count($price_arr) === 1)
		    {
		        $price = $price_arr[0]['price'] * $qty;
		    }
		}else{
			$day = strtolower(date("l", $start_ts));
			if ($wt_arr !== false && $wt_arr['is_dayoff'] == 'F')
			{
				$price_day_arr = pjPriceDayModel::factory()
					->where('t1.calendar_id', $calendar_id)
					->where('t1.day', $day)
					->where('t1.start_time', date("H:i:s", $start_ts))
					->where('t1.end_time', date("H:i:s", $end_ts))
					->orderBy('t1.start_time ASC')
					->limit(1)
					->findAll()
					->getData();
				if (count($price_day_arr) === 1)
				{
					$price = $price_day_arr[0]['price'] * $qty;
				} else {
					$price = (float) $wt_arr['price'] * $qty;
				}
			}
		}
		return $price;
	}
	
	public static function getCartTotal($calendar_id, $cart, $option_arr)
	{
		$pjWorkingTimeModel = pjWorkingTimeModel::factory();
		
		$original_price = 0;
		$price = 0;
		$discount = 0;
		if (!$cart->isEmpty())
		{
			$cart_arr = $_SESSION['TSBC_Cart'];
			
			foreach ($cart_arr as $cid => $date_arr)
			{
				if ($cid != $calendar_id)
				{
					continue;
				}
				
				$wt_data = $pjWorkingTimeModel->getWorkingTime($cid);
				foreach ($date_arr as $date => $time_arr)
				{
					$wt_arr = $pjWorkingTimeModel->filterDate($wt_data, $date);
					foreach ($time_arr as $time => $qty)
					{
						list($start_ts, $end_ts) = explode("|", $time);
						$qty = $_SESSION['TSBC_Slots'][$cid][$time];
						$slot_price = pjAppController::getPrices($cid, $wt_arr, $date, $start_ts, $end_ts, $qty);
						$original_price += $slot_price;
						if(isset($cart_arr['voucher_data'][$start_ts]))
						{
						    $discount_record = $cart_arr['voucher_data'][$start_ts];
						    if($discount_record['status'] == 'OK' && isset($discount_record['arr']))
						    {
    						    $_discount = $discount_record['arr']['discount'];
    						    if($discount_record['arr']['type'] == 'percent')
    						    {
    						        $_discount = $slot_price * $discount_record['arr']['discount'] / 100; 
    						    }
    						    if($_discount > $slot_price)
    						    {
    						        $_discount = $slot_price;
    						    }
    						    $discount += $_discount;
    						    $slot_price -= $_discount;
						    }
						}
						if($slot_price < 0)
						{
						    $slot_price = 0;
						}
						$price += $slot_price;
					}
				}
			}
		}
		
		$tax = ($price * $option_arr['o_tax']) / 100;
		$total = $price + $tax;
		switch ($option_arr['o_deposit_type'])
		{
			case 'amount':
				$deposit = $option_arr['o_deposit'];
				break;
			case 'percent':
			default:
				$deposit = ($total * $option_arr['o_deposit']) / 100;
				break;
		}

		return array('original_price' => round($original_price, 2), 'price' => round($price, 2), 'total' => round($total, 2), 'deposit' => round($deposit, 2), 'tax' => round($tax, 2), 'discount' => round($discount, 2));
	}
	
	public static function getCartPrices($calendar_id, $cart)
	{
		$pjDateModel = pjDateModel::factory();
		$pjWorkingTimeModel = pjWorkingTimeModel::factory();
		$pjPriceModel = pjPriceModel::factory();
		$pjPriceDayModel = pjPriceDayModel::factory();
		
		$_arr = array();
		$cart_arr = $cart->getAll();
		foreach ($cart_arr as $cid => $date_arr)
		{
			if ($cid != $calendar_id)
			{
				continue;
			}
			$wt_data = $pjWorkingTimeModel->getWorkingTime($calendar_id);
			foreach ($date_arr as $date => $time_arr)
			{
				$wt_arr = $pjWorkingTimeModel->filterDate($wt_data, $date);
				foreach ($time_arr as $time => $q)
				{
					list($start_ts, $end_ts) = explode("|", $time);
					
					$index = $time;
					$_arr[$index] = 0;
					
					$_arr[$index] = pjAppController::getPrices($calendar_id, $wt_arr, $date, $start_ts, $end_ts, 1);
				}
			}
		}
		# NB: Higher RANK gets bigger precedence!
		return array($calendar_id => $_arr);
	}
	
	public static function getPricesDate($calendar_id, $date, $option_arr)
	{
		$t_arr = pjAppController::getDailySlots($calendar_id, $date, $option_arr);
		if ($t_arr === false)
		{
			# It's Day off
			return false;
		}
		
		$pjWorkingTimeModel = pjWorkingTimeModel::factory();
				
		$wt_data = $pjWorkingTimeModel->getWorkingTime($calendar_id);
		$wt_arr = $pjWorkingTimeModel->filterDate($wt_data, $date);
		
		$_arr = array();
		$step = $t_arr['slot_length'] * 60;
		# Fix for 24h support
		$offset = $t_arr['end_ts'] <= $t_arr['start_ts'] ? 86400 : 0;
		$day = strtolower(date("l", strtotime($date)));
	
		$slots = $t_arr['slots'];
		$i = $t_arr['start_ts'];
		$lunch_from_ts = $t_arr['lunch_start_ts'];
		$lunch_to_ts = $t_arr['lunch_end_ts'];
		if($lunch_from_ts < $i)
		{
			$lunch_from_ts = $lunch_from_ts + (24 * 60 * 60);
			$lunch_to_ts = $lunch_to_ts + (24 * 60 * 60);
		}
		for($n = 1; $n <= $slots; $n++)
		{
			$index = $i . "|" . ($i + $step);
			$_arr[$index] = 0;
			
			$_arr[$index] = pjAppController::getPrices($calendar_id, $wt_arr, $date, $i, ($i + $step), 1);
			if($i + $step == $lunch_from_ts)
			{
				$i = $lunch_to_ts;
			}else{
				$i = $i + $step;
			}
		}
		# NB: Higher RANK gets bigger precedence!
		return $_arr;
	}
	public static function getTimeByDates($calendar_ids, $date)
	{
	    $result = array();
	    $pjWorkingTimeModel = pjWorkingTimeModel::factory();
	    $pjDateModel = pjDateModel::factory();
	    foreach($calendar_ids as $cid)
	    {
	        $date_arr = $pjDateModel->reset()->getDailyWorkingTime($cid, $date);
	        if ($date_arr === false)
	        {
	            $wt_data = $pjWorkingTimeModel->reset()->getWorkingTime($cid);
	            $wt_arr = $pjWorkingTimeModel->filterDate($wt_data, $date);
	            $t_arr = $wt_arr;
	        } else {
	            $t_arr = $date_arr;
	        }
	        
	        if($t_arr != false && $t_arr['is_dayoff'] == 'F')
	        {
	            if(isset($result['start_ts']))
	            {
	                if($t_arr['start_ts'] < $result['start_ts'])
	                {
	                    $result['start_ts'] = $t_arr['start_ts'];
	                }
	            }else{
	                $result['start_ts'] = $t_arr['start_ts'];
	            }
	            if(isset($result['end_ts']))
	            {
	                if($t_arr['end_ts'] > $result['end_ts'])
	                {
	                    $result['end_ts'] = $t_arr['end_ts'];
	                }
	            }else{
	                $result['end_ts'] = $t_arr['end_ts'];
	            }
	            if($t_arr['lunch_start_ts'] != $t_arr['lunch_end_ts'])
	            {
    	            $result['lunch_start_ts'] = $t_arr['lunch_start_ts'];
    	            $result['lunch_end_ts'] = $t_arr['lunch_end_ts'];
	            }
	        }
	    }
	    return $result;
	}
	public static function getDailySlots($calendar_id, $date, $option_arr)
	{
		$date_arr = pjDateModel::factory()->getDailyWorkingTime($calendar_id, $date);
		
		if ($date_arr === false)
		{
			# There is not custom working time/prices for given date, so get for day of week (Monday, Tuesday...)
			$pjWorkingTimeModel = pjWorkingTimeModel::factory();
			$wt_data = $pjWorkingTimeModel->getWorkingTime($calendar_id);
			$wt_arr = $pjWorkingTimeModel->filterDate($wt_data, $date);

			//$wt_arr['slot_length'] = $option_arr['slot_length'];
			$t_arr = $wt_arr;
		} else {
			# There is custom working time/prices for given date
			$t_arr = $date_arr;
		}
		
		return $t_arr;
	}
	
	public static function getWeeklySlots($calendar_id, $iso_date)
	{
		$date_arr = pjDateModel::factory()->getWeeklyWorkingTime($calendar_id, $iso_date);
		
		$pjWorkingTimeModel = pjWorkingTimeModel::factory();
		$wt_data = $pjWorkingTimeModel->getWorkingTime($calendar_id);

		$t_arr = array();
		foreach ($date_arr as $date => $item)
		{
			$t_arr[$date] = array();
			
			# There is not custom working time/prices for given date, so get for day of week (Monday, Tuesday...)
			if (empty($item))
			{
				$t_arr[$date] = $pjWorkingTimeModel->filterDate($wt_data, $date);
				continue;
			}
			
			$t_arr[$date] = $item;
		}
		
		return $t_arr;
	}
	
	public static function getMonthlySlots($calendar_id, $month, $year)
	{
		$date_arr = pjDateModel::factory()->getMonthlyWorkingTime($calendar_id, $month, $year);
		
		$pjWorkingTimeModel = pjWorkingTimeModel::factory();
		$wt_data = $pjWorkingTimeModel->getWorkingTime($calendar_id);

		$t_arr = array();
		foreach ($date_arr as $date => $item)
		{
			$t_arr[$date] = array();
			
			# There is not custom working time/prices for given date, so get for day of week (Monday, Tuesday...)
			if (empty($item))
			{
				$t_arr[$date] = $pjWorkingTimeModel->filterDate($wt_data, $date);
				continue;
			}
			
			$t_arr[$date] = $item;
		}
		
		return $t_arr;
	}
	
	public static function getMonthStatus($calendar_id, $month, $year, $option_arr)
	{
		$numOfDays = date("t", mktime(0, 0, 0, $month, 1, $year));
		$_arr = array();
		foreach (range(1, $numOfDays) as $i)
		{
			$_arr[date("Y-m-d", mktime(0, 0, 0, $month, $i, $year))] = array('code' => 1, 'text' => 'free');
		}
		
		$bookings = pjBookingSlotModel::factory()->getBookings($calendar_id, $month, $year);
		$monthlySlots = pjAppController::getMonthlySlots($calendar_id, $month, $year);
		$now = time();
		foreach ($monthlySlots as $date => $t_arr)
		{
			if (empty($t_arr) || (isset($t_arr['is_dayoff']) && $t_arr['is_dayoff'] == 'T'))
			{
				continue;
			}
			$step = $t_arr['slot_length'] * 60;
			# Fix for 24h support
			$offset = $t_arr['end_ts'] <= $t_arr['start_ts'] ? 86400 : 0;

			$dailyAv = 0;
			$dailyBo = 0;
			
			$slots = $t_arr['slots'];
			$i = $t_arr['start_ts'];
			$lunch_from_ts = $t_arr['lunch_start_ts'];
			$lunch_to_ts = $t_arr['lunch_end_ts'];
			if($lunch_from_ts < $i)
			{
			    $lunch_from_ts = $lunch_from_ts + 86400;
			    $lunch_to_ts = $lunch_to_ts + 86400;
			}
			for($n = 1; $n <= $slots; $n++)
			{
				$cnt_booked = 0;
			    foreach ($bookings[$date] as $bs)
			    {
			        if ($bs['start_ts'] == $i && $bs['end_ts'] == $i + $step)
			        {
			            $dailyBo += $bs['cnt'];
			            $cnt_booked += $bs['cnt'];
			        }
			    }
				if ($i < $now || ($i < $now + $option_arr['o_hours_before'] * 3600))
				{
					$dailyBo += $t_arr['slot_limit'] - $cnt_booked;
				}
			    $dailyAv += $t_arr['slot_limit'];
			    if($i + $step == $lunch_from_ts)
			    {
			        $i = $lunch_to_ts;
			    }else{
			        $i = $i + $step;
			    }
			}
			
			if ($dailyBo > 0 && $dailyAv > $dailyBo)
			{
			    $_arr[$date] = array('code' => 2, 'text' => 'partly');
			} elseif ($dailyAv <= $dailyBo) {
			    $_arr[$date] = array('code' => 3, 'text' => 'fully');
			}
		}
		return $_arr;
	}
}
?>