<?php 
// gets availability from package item id

require('rezgo/include/page_header.php');

// start a new instance of RezgoSite
$site = new RezgoSite();
$time_format = isset($_REQUEST['time_format']) ? (string) sanitize_text_field($_REQUEST['time_format'] . ' hours') : '';

$rezgoAction = isset($_REQUEST['rezgoAction']) ? sanitize_text_field($_REQUEST['rezgoAction']) : '';
$type = isset($_REQUEST['type']) ? sanitize_text_field($_REQUEST['type']) : '';

$r_date = is_array($_REQUEST['date']) ? array_map('sanitize_text_field', $_REQUEST['date']) : sanitize_text_field($_REQUEST['date']);
$chosenDate = is_array($_REQUEST['chosenDate']) ? array_map('sanitize_text_field', $_REQUEST['chosenDate']) : sanitize_text_field($_REQUEST['chosenDate']);

$option = isset($_REQUEST['option']) ? (int) sanitize_text_field($_REQUEST['option']) : '';
$com = isset($_REQUEST['com']) ? (int) sanitize_text_field($_REQUEST['com']) : '';
$js_timestamp = isset($_REQUEST['js_timestamp']) ? (int) sanitize_text_field($_REQUEST['js_timestamp']) : '';
$js_timezone = isset($_REQUEST['js_timezone']) ? (int) sanitize_text_field($_REQUEST['js_timezone']) : '';


$within = isset($_REQUEST['within']) ? sanitize_text_field($_REQUEST['within']) : '';
$within_in_hours = isset($_REQUEST['within_in_hours']) ? (float) sanitize_text_field($_REQUEST['within_in_hours']) * 60 * 60 : '';
$bookable = isset($_REQUEST['bookable']) ? sanitize_text_field($_REQUEST['bookable']) : '';
$spacing = isset($_REQUEST['spacing']) ? (float) sanitize_text_field($_REQUEST['spacing']) * 60 * 60 : ''; // convert to seconds, to account for decimalpoints (.5 hr increments)
$end_time = isset($_REQUEST['end_time']) ? (int) sanitize_text_field($_REQUEST['end_time']) : '';
$prev_date =  isset($_REQUEST['prev_date']) ? (string) sanitize_text_field($_REQUEST['prev_date']) : '';
$selected_time = (isset($_REQUEST['selected_time']) && $_REQUEST['selected_time'] !== '') ? sanitize_text_field($_REQUEST['selected_time']) : 0;
$selected_duration = isset($_REQUEST['selected_duration']) ? sanitize_text_field($_REQUEST['selected_duration']) : '';
$pax_array = isset($_REQUEST['pax']) ? array_map('sanitize_text_field', $_REQUEST['pax']) : '';
$discount = isset($_REQUEST['discount']) ? (sanitize_text_field((float)$_REQUEST['discount'])/100) : '';
$package_index = isset($_REQUEST['package_index']) ? (int) sanitize_text_field($_REQUEST['package_index']) : '';
$package = (int) sanitize_text_field($_REQUEST['package']);
$cooldown = '';

if (REZGO_WORDPRESS) $site->setTimeZone();

function isDateInRange($dateTime, $lowerBound, $upperBound) {
	return ($dateTime >= $lowerBound) && ($dateTime <= $upperBound);
}

	// return total amount due in correct currency format
	if ($rezgoAction == 'formatCurrency'){
		// echo $site->formatCurrency($num);
		$currency_symbol = isset($_REQUEST['currency_symbol']) ? (string) sanitize_text_field($_REQUEST['currency_symbol']) : '$';
		$currency_decimals = isset($_REQUEST['currency_decimals']) ? (int) sanitize_text_field($_REQUEST['currency_decimals']) : 2;
		$currency_separator = isset($currency_separator) ? (string)$currency_separator : null;

		$pre = '';
		$num = sanitize_text_field($_REQUEST['amount']);
		if (strpos((string)$num, "-") !== false) {
			$num = str_replace("-", "", $num);
			$pre = '- ';
		}
		echo str_replace(" ", "&nbsp;", $pre.$currency_symbol.number_format((float)$num, (int)$currency_decimals, '.', (string)$currency_separator));
	}

if ($rezgoAction == 'price') {

	$package_options = $site->getTours('t=com&q='.$package);
	$included_uids = [];

	// gather available options from package items
	foreach ($package_options[0]->packages->package[$package_index]->choice as $package_option) {
		$included_uids[] = (int)$package_option->id;
	}

	$availability_title = '';	

	if (isset($_REQUEST['option_num'])) {
		$option_num = sanitize_text_field($_REQUEST['option_num']);
	} else {
		$option_num = 1;	
		
		if ($type != 'open') {
			$now = time();
			$offset_time_now = strtotime($time_format, $now);
			
      		// $today = date('Y-m-d', $now);
			// $selected_date = date('Y-m-d', strtotime($r_date . ' ' . sanitize_text_field($_REQUEST['time_format']) . ' hours'));
			// $selected_date = date('Y-m-d', strtotime($r_date));
			// $available_day = date('D', strtotime($r_date));
      		// $available_date = date((string) sanitize_text_field($_REQUEST['date_format']), strtotime($r_date)); 
      
		}
	}

	if ($type === 'single'){

		function has_duplicates($array) {
			return count($array) !== count(array_unique($array));
		}
		function get_duplicates($array) {
			return array_unique( array_diff_assoc( $array, array_unique( $array ) ) );
		}

		$options = array();
		$single_options = array();
		$same_dates = get_duplicates($r_date);

		// handle multiple items on the same date
		if (has_duplicates($r_date)){
			foreach ($same_dates as $date) {
				$single_options[] = $site->getTours('t=com&q='.$com.'&d='.$date.'&package='.$package);
			}
			foreach ($single_options as $tour) {
				if (is_array($tour)){
					foreach ($tour as $v) {
						$options[] = $v;
					}
				} else {
					$options[] = $tour;
				}
			} unset($tour); unset($single_options);
		}

		// add in other remaining dates if applicable
		$remaining_dates = array_diff($r_date, $same_dates);
		if ($remaining_dates) {
			foreach ($remaining_dates as $date) {
				$single_options[] = $site->getTours('t=com&q='.$_REQUEST['com'].'&d='.$date.'&package='.$package);
			}
			foreach ($single_options as $tour) {
				if (is_array($tour)){
					foreach ($tour as $v) {
						$options[] = $v;
					}
				} else {
					$options[] = $tour;
				}
			} 
		}

	} else {
		$options = $site->getTours('t=com&q='.$com.'&d='.$r_date.'&package='.$package);
	}
	
	if ($options) {

		$dynamic_start_times = [];
		$avail_options = (object) [];
				
		// get current package restriction to show/hide selectable options 
		$current_restrictions = $package_options[0]->packages->package[$package_index]->bookable || $package_options[0]->packages->package[$package_index]->spacing ? 1 : 0;

		// assign a new end time based on different start times
		if ($selected_time) {
			// use selected date to compare times
			$selected_time = strtotime((string)$prev_date.$selected_time);

			// convert 'night' to 'days'
			$selected_duration = strpos($selected_duration, 'night') !== false ? (int)$selected_duration . ' days' : $selected_duration;

			// convert hours to seconds
			if (strpos($selected_duration, 'hours') !== false){
				$selected_duration = $selected_duration * 60 * 60 . ' seconds';
			}
			$end_time = strtotime('+'.$selected_duration, $selected_time);
		}

		$cooldown = strtotime('+'.((int)$spacing - 1).' seconds', $end_time);

		$c = 0;
		foreach($options as $option) {
			$site->readItem($option);

			// only include items added in the package
			if (in_array((int)$option->uid, $included_uids)){ 

				$prices = (object) [];

				$item = $site->getItem();
				$time_format = (string)$option->time_format;

				if ($time_format == 'static') {
					$start_time = (int)$item->date->start_time;

					// ignore cooldown on next open/single date availability options
					if ((string)$option->date->value == 'open' || (string)$option->date_selection == 'single') {
						$cooldown = 0;
					}

					if ($current_restrictions) {
						$selectable_time = ($start_time > $cooldown) ? 1 : 0;
					} else {
						$selectable_time = 1;
					}

				} else {
					foreach ($option->date->time_data->time as $time) {
						$chosenDateTime = $chosenDate.$time->id;

						if (is_array($chosenDate)) {
							foreach ($chosenDate as $v) {
								$chosenDateTime = $v.$time->id;
								// check if at least one time option is available
								if (strtotime($chosenDateTime) > $cooldown){
									$dynamic_start_times[] = strtotime($chosenDateTime);
								}
							}
						} else {

							// we could book on any date, just not the same duration as the first
							if (!$current_restrictions) {

								if (!isDateInRange(strtotime($chosenDateTime), $selected_time, $cooldown)) {
									$dynamic_start_times[] = $chosenDate.$time->id;
								}

							} else {
								// check if at least one time option is available
								if (strtotime($chosenDateTime) > $cooldown){
									$dynamic_start_times[] = strtotime($chosenDateTime);
								}
							}

						}
					}

					$selectable_time = $dynamic_start_times ? 1 : 0;
				}

				if ((int)$item->total_availability !== 0 && $selectable_time) {

					// explicitly instantiate objects
					$avail_options->options[$c] = (object)[];
					$prices = (object)[];

					$avail_options->options[$c]->uid = (int)$option->uid;
					$avail_options->options[$c]->com = (int)$option->com;
					$avail_options->options[$c]->item = (string)$option->item;
					$avail_options->options[$c]->name = (string)$option->option;
					$avail_options->options[$c]->index = (string)$c;

					if ($time_format == 'dynamic'){
						$avail_options->options[$c]->time_format = $time_format;

						foreach ($option->date->time_data->time as $time) {
							$cutoff_operator = '+';
							if (strpos($option->cutoff, '-') !== false) {
								$option_cutoff = str_replace('-', '', $option->cutoff);
								$cutoff_operator = '-';
							}
							$option_cutoff = round((float)$option->cutoff * 60);
							$cutoff_time = strtotime($cutoff_operator .$option_cutoff. ' minutes', strtotime($r_date.$time->id) );
							$passed = $offset_time_now > $cutoff_time ? 1 : 0;

							// calculate times that are outside of the 'within_in_hours' range
							$within_time_restriction = 1;
							if ($within_in_hours) {
								$calculate_within_restriction = strtotime('+'.($within_in_hours).' seconds', $selected_time);
								$within_time_restriction = strtotime((string)$option->date->value.$time->id) <= $calculate_within_restriction ? 1 : 0;
							}

							if (!$current_restrictions) {

								if ((int)$time->av > 0 && !isDateInRange(strtotime($chosenDate.$time->id), $selected_time, $cooldown) && !$passed){
									$avail_options->options[$c]->book_time[] = (string)$time->id.':::'.(string)$time->av;
								}
							} else {
								if ((int)$time->av > 0 && strtotime((string)$option->date->value.$time->id) > $cooldown && !$passed && $within_time_restriction){
									$avail_options->options[$c]->book_time[] = (string)$time->id.':::'.(string)$time->av;
								}
							}
						}
						$avail_options->options[$c]->hide_av = $option->date->hide_availability ? 1 : 0;
					}

					$prices->price_adult = ($item->date->price_adult) ? (float) $item->date->price_adult : 0;
					$prices->price_child = ($item->date->price_child) ? (float) $item->date->price_child : 0;
					$prices->price_senior = ($item->date->price_senior) ? (float) $item->date->price_senior : 0;
					$prices->price4 = ($item->date->price4) ? (float) $item->date->price4 : 0;
					$prices->price5 = ($item->date->price5) ? (float) $item->date->price5 : 0;
					$prices->price6 = ($item->date->price6) ? (float) $item->date->price6 : 0;
					$prices->price7 = ($item->date->price7) ? (float) $item->date->price7 : 0;
					$prices->price8 = ($item->date->price8) ? (float) $item->date->price8 : 0;
					$prices->price9 = ($item->date->price9) ? (float) $item->date->price9 : 0;

					// add in pax_obj info
					foreach ($pax_array as $pax => $num) {
						$avail_options->options[$c]->pax[] = intval($num);
					}

					foreach( $prices as $price ) {
						$discount_off = (float) ($price * $discount);
						$avail_options->options[$c]->price[] = ($price) ? ($price - $discount_off) : 0;
					}

					// total everything up to send to FE
					foreach ($avail_options as $options){

						for ($i = 0; $i < count($avail_options->options[$c]->pax) ; $i++) { 
							$avail_options->options[$c]->total[] = $options[$c]->price[$i] * (int)$options[$c]->pax[$i];
						}
						$avail_options->options[$c]->option_total = array_sum($avail_options->options[$c]->total);
					}

					$avail_options->options[$c]->option_total_formatted = $site->formatCurrency($avail_options->options[$c]->option_total); 

					// add all other details
					$avail_options->options[$c]->chosen_date = $chosenDate ? $chosenDate : '';
					$avail_options->options[$c]->bookable = $bookable ? $bookable : '';
					$avail_options->options[$c]->within = $within ? $within : '';
					$avail_options->options[$c]->within_in_hours = $within_in_hours ? $within_in_hours : '';

					// add date if available on a single date
					$avail_options->options[$c]->single_date = (string)$option->date_selection === 'single' ? date('Y-m-d', (int)$option->start_date) : '';

					// add 'open availability' if open avail
					$avail_options->options[$c]->open_date = (string)$option->date->value === 'open' ? 'Open Availability' : '';

					// add start and end times with duration
					$avail_options->options[$c]->start_time = $option->date->start_time ? (int)$option->date->start_time : '';
					$avail_options->options[$c]->end_time = $option->date->end_time ? (int)$option->date->end_time : '';
					$avail_options->options[$c]->duration = $option->duration ? (string)$option->duration : '';

					$c++;
				}
			}

    	} // end foreach($options as $option) 
	}

	echo (isset($avail_options) && $avail_options != new stdClass()) ? json_encode($avail_options) : 0;
}

?>