<?php

if ( ! defined( 'ABSPATH' ) ) exit;                                             // Exit if accessed directly            // FixIn: 9.8.0.4.


if ( ! defined( 'WPBC_FULL_DAY_TIME_IN' ) ) {  define( 'WPBC_FULL_DAY_TIME_IN'    , 1 ); }          // =                          +1 sec.               '00:00:01'
if ( ! defined( 'WPBC_FULL_DAY_TIME_OUT' ) ) { define( 'WPBC_FULL_DAY_TIME_OUT'   , 86392 ); }      // = 24 * 60 * 60 = 86400  - 10 sec. + 2 sec.       '23:59:52'

// ---------------------------------------------------------------------------------------------------------------------
// Intervals
// ---------------------------------------------------------------------------------------------------------------------

/**
 * Merge several  intersected intervals or return not intersected:                        [[1,3],[2,6],[8,10],[15,18]]  ->   [[1,6],[8,10],[15,18]]
 *
 * @param array $intervals      [ [1,3],[2,4],[6,8],[9,10],[3,7] ]
 *
 * @return array                [ [1,8],[9,10] ]
 *
 * Example:     wpbc_merge_intersected_intervals(  array(  array(1,3), array(2,4), array(6,8), array(9,10), array(3,7)  );      ->    array(  array(1,8), array(9,10)  )
 */
function wpbc_merge_intersected_intervals( $intervals ){

	if ( empty( $intervals ) ) {
		return array();
	}

    $merged = array();

	// Sort array by first value in a list          [[8,10],[1,3],[15,18],[2,6]]    ->      [[1,3],[2,6],[8,10],[15,18]]
	usort( $intervals, function ( $compare_A, $compare_B ) {
		if ( $compare_A[0] > $compare_B[0] ) {
			return 1;
		} elseif ( $compare_A[0] < $compare_B[0] ) {
			return - 1;
		}
		return 0;
	} );


	$merged_interval = $intervals[0];                           // [1,3]

	for ( $i = 1; $i < count( $intervals ); $i ++ ) {
		$next_element = $intervals[ $i ];                       // [2,6]

		if ( $next_element[0] <= $merged_interval[1] ) {
			$merged_interval[1] = max( $merged_interval[1], $next_element[1] );
		} else {
			$merged[]        = $merged_interval;
			$merged_interval = $next_element;
		}
	}

	$merged[] = $merged_interval;

    return $merged;
}


/**
 * Is 2 intervals intersected:       [36011, 86392]    <=>    [1, 43192]  =>  true      ( intersected )
 *
 * Good explanation  here https://stackoverflow.com/questions/3269434/whats-the-most-efficient-way-to-test-if-two-ranges-overlap
 *
 * @param array $interval_A   array( 36011, 86392 )
 * @param array $interval_B   array(     1, 43192 )
 *
 * @return bool
 */
function wpbc_is__intervals__intersected( $interval_A, $interval_B ) {

	if (
			( empty( $interval_A ) )
	     || ( empty( $interval_B ) )
	){
		return false;
	}

	$is_intersected = max( $interval_A[0], $interval_B[0] ) - min( $interval_A[1], $interval_B[1] );

	// if ( 0 == $is_intersected ) {
	//	                                 // Such ranges going one after other, e.g.: [ 12, 15 ] and [ 15, 21 ]
	// }

	if ( $is_intersected < 0 ) {
		return true;                     // INTERSECTED
	}

	return false;                       // Not intersected
}



// ---------------------------------------------------------------------------------------------------------------------
//  Time - Slots    functions
// ---------------------------------------------------------------------------------------------------------------------

	/**
	 * Get time in seconds from  SQL date format               '2024-01-28 12:00:02' -> 1706443192
	 *
	 * @param $sql_date__ymd_his     '2024-01-28 12:00:02'  Date in SQL format
	 * @param bool $is_apply__check_in_out__10s          : check_in_time = +10sec     check_out_time = -10sec
	 *
	 * @return int
	 *
	 *            if $is_apply__check_in_out__10s == true (it's default)
	 *
	 *            then apply   +10 seconds for check  in time         it's time, that  ended with  1
	 *            and  apply   -10 seconds for check out time         it's time, that  ended with  2

	 */
	function wpbc_convert__sql_date__to_seconds( $sql_date__ymd_his, $is_apply__check_in_out__10s = true  ){

		list( $sql_date_ymd, $sql_time_his ) = explode( ' ', $sql_date__ymd_his );                                      // '2024-01-28',  '12:00:02'

		$date_in_seconds = wpbc_convert__date_ymd__to_seconds( $sql_date_ymd );
		$time_in_seconds = wpbc_convert__time_his__to_seconds( $sql_time_his, $is_apply__check_in_out__10s );

		$in_seconds = $date_in_seconds + $time_in_seconds;

		return $in_seconds;
	}


		/**
		 * Get date in seconds from  SQL only_date format          '2024-01-28' -> 1706400000
		 *
		 * @param $sql_date_ymd     '2024-01-28'
		 *
		 * @return int
		 */
		function wpbc_convert__date_ymd__to_seconds( $sql_date_ymd ){

			// DATE
			$sql_date_time = $sql_date_ymd . ' 00:00:00';

			$in_seconds = strtotime( $sql_date_time );

			return $in_seconds;
		}


		/**
		 * Get time in seconds from  SQL time format                '12:00:02' -> 43192
		 *
		 * @param string $sql_time_his     '12:00:02'
		 * @param bool $is_apply__check_in_out__10s          : check_in_time = +10sec     check_out_time = -10sec
		 *
		 * @return int
		 *
		 *            if $is_apply__check_in_out__10s == true (it's default)
		 *
		 *            then apply   +10 seconds for check  in time         it's time, that  ended with  1
		 *            and  apply   -10 seconds for check out time         it's time, that  ended with  2
		 */
		function wpbc_convert__time_his__to_seconds( $sql_time_his, $is_apply__check_in_out__10s = true ){

			// TIME
			$in_seconds = explode( ':', $sql_time_his );

			$in_seconds = intval( $in_seconds[0] ) * 60 * 60 + intval( $in_seconds[1] ) * 60 + intval( $in_seconds[2] );        // 43202

			if ( $is_apply__check_in_out__10s ) {

				$is_check_in_out__or_full = $in_seconds % 10;                                                                       // 0, 1, 2

				if ( 1 == $is_check_in_out__or_full ) {
					$in_seconds += 10;
				}
				if ( 2 == $is_check_in_out__or_full ) {
					$in_seconds -= 10;
				}
			}

			$in_seconds = intval( $in_seconds );

			return $in_seconds;
		}


		/**
		 * Get time in SQL time format from  seconds                43192  ->  '12:00:02'
		 *
		 * @param int $in_seconds                               43192
		 * @param bool $is_apply__check_in_out__10s          : check_in_time = +10sec     check_out_time = -10sec
		 *
		 * @return int
		 *
		 *            if $is_apply__check_in_out__10s == true (it's default)
		 *
		 *            then apply   +10 seconds for check  in time         it's time, that  ended with  1
		 *            and  apply   -10 seconds for check out time         it's time, that  ended with  2
		 */
		function wpbc_convert__seconds__to_time_his( $in_seconds, $is_apply__check_in_out__10s = true ){

			//$is_check_in_out__or_full = $seconds__this__booking % 10;                                                       // 1, 2  (not 0)
			$is_check_in_out__or_full = substr( ( (string) $in_seconds ), -1 );                           // '1', '2'  (not '0')

			if ( '1' == $is_check_in_out__or_full ) {
				if ( WPBC_FULL_DAY_TIME_IN == $in_seconds ) {           // situation: 00:00     e.g. 1 sec.
					$in_seconds = 0;
				} else {
					$in_seconds = $in_seconds - 10 - 1;
				}
			}
			if ( '2' == $is_check_in_out__or_full ) {
				if ( WPBC_FULL_DAY_TIME_OUT == $in_seconds ) {           // situation: 24:00     e.g. 86400 -10 +2 sec.
					$in_seconds = 86400;
				} else {
					$in_seconds = $in_seconds + 10 - 2;
				}
			}

			$rest_without_hours_as_seconds = $in_seconds % ( 60 * 60 );

			$in_hours = ( $in_seconds - $rest_without_hours_as_seconds ) / ( 60 * 60 );                                     // 43200
			$in_hours = intval( $in_hours );    // from 20.99 hours get 20          // round( $in_hours,   0, PHP_ROUND_HALF_DOWN );

			$in_minutes = $rest_without_hours_as_seconds / 60;                                                                // 43200
			$in_minutes = intval( $in_minutes );  // from 55.99 minutes get 55        // round( $in_minutes, 0, PHP_ROUND_HALF_DOWN );     // making 1.5 into 1 and -1.5 into -1.

			$in_only_seconds = $in_seconds - ( $in_hours * 60 * 60 ) - ( $in_minutes * 60 );                           // 43200
			$in_only_seconds = intval( $in_only_seconds );  // from 55.99 minutes get 55        // round( $in_minutes, 0, PHP_ROUND_HALF_DOWN );     // making 1.5 into 1 and -1.5 into -1.

			if ( '1' == $is_check_in_out__or_full ) {
				$in_only_seconds += 1;
			}
			if ( '2' == $is_check_in_out__or_full ) {
				$in_only_seconds += 2;
			}


			$in_hours        = ( $in_hours < 10 ) ? '0' . $in_hours : $in_hours;
			$in_minutes      = ( $in_minutes < 10 ) ? '0' . $in_minutes : $in_minutes;
			$in_only_seconds = ( $in_only_seconds < 10 ) ? '0' . $in_only_seconds : $in_only_seconds;

			$sql_time_his = $in_hours . ':' . $in_minutes . ':'. $in_only_seconds;

			return $sql_time_his;
		}


	/**
	 * Convert date timestamp (date in seconds)  to  SQL date format            1706400000 -> '2024-01-28 00:00:00'
	 *
	 * @param int $in_seconds                       1706400000
	 * @param bool $is_apply__check_in_out__10s     true                    : check_in_time = -10sec     check_out_time = +10sec
	 * @param string $sql_date_format               'Y-m-d H:i:s'           : sometimes need to have ''Y-m-d 00:00:01' or other...
	 *
	 * @return false|string                         '2024-01-28 00:00:00'
	 */
	function wpbc_convert__seconds__to_sql_date( $in_seconds, $is_apply__check_in_out__10s = true, $sql_date_format = 'Y-m-d H:i:s' ){

		if ( $is_apply__check_in_out__10s ) {

			$is_check_in_out__or_full = $in_seconds % 10;                                                                       // 0, 1, 2

			if ( 1 == $is_check_in_out__or_full ) {
				$in_seconds -= 10;
			}
			if ( 2 == $is_check_in_out__or_full ) {
				$in_seconds += 10;
			}
		}

		$sql_date = gmdate( $sql_date_format, $in_seconds );

		return $sql_date;
	}

	// -----------------------------------------------------------------------------------------------------------------

	/**
	 * Convert usual to seconds time range     "10:15 - 12:00"    ->    "36911 - 43192"
	 *
	 * It's means that "10:15 - 12:00" in seconds "36900 - 43200"   and with intersection fix:  "(36900 +10 +1) - (43200 -10 +2)" e.g. "36911 - 43192"
	 *
	 * @param string $readable_time_slot        "10:15 - 12:00"
	 *
	 * @return string time_range_in_seconds     "36911 - 43192"
	 */
	function wpbc_convert__readable_time_slot__to__time_range_in_seconds( $readable_time_slot ) {

		$rangeA_arr = explode( '-', $readable_time_slot );
		$rangeA_arr[0] =  trim( $rangeA_arr[0] );
		$rangeA_arr[1] =  trim( $rangeA_arr[1] );

		$time_range_in_seconds = array();

		foreach ( $rangeA_arr as $is_end_time => $only_time ) {                 // $is_end_time = 0 | 1

			$in_seconds = explode( ':', $only_time );
			$in_seconds = intval( $in_seconds[0] ) * 60 * 60 + intval( $in_seconds[1] ) * 60;                               // 43200

			if ( ! $is_end_time ) {

				if ( 0 == $in_seconds ) {               // situation: 00:00     e.g. 0 sec.
					$in_seconds = WPBC_FULL_DAY_TIME_IN;
				} else {
					$in_seconds = $in_seconds + 10 + 1;
				}

			} else {

				if ( 86400 == $in_seconds ) {           // situation: 24:00     e.g. 86400 sec.
					$in_seconds = WPBC_FULL_DAY_TIME_OUT;
				} else {
					$in_seconds = $in_seconds - 10 + 2;
				}

			}

			$time_range_in_seconds[] = $in_seconds;
		}

		$time_range_in_seconds = implode( ' - ', $time_range_in_seconds );

		return $time_range_in_seconds;
	}


	/**
	 * Convert seconds to usual time range:     "36911 - 43192"    ->    "10:15 - 12:00"
	 *
	 * It's means  "36911 - 43192"  with intersection fix:  "(36900 +10 +1) - (43200 -10 +2)" e.g. in seconds "36900 - 43200"     is equal to    "10:15 - 12:00"
	 *
	 * @param string $time_range_in_seconds                  "36911 - 43192"
	 *
	 * @return string $time_slot      "10:15 - 12:00"
	 */
	function wpbc_convert__time_range_in_seconds__to__readable_time_slot( $time_range_in_seconds ) {

		$rangeA_arr = explode( '-', $time_range_in_seconds );
		$rangeA_arr[0] =  intval( trim( $rangeA_arr[0] ) );
		$rangeA_arr[1] =  intval( trim( $rangeA_arr[1] ) );

		$time_slot = array();

		foreach ( $rangeA_arr as $is_end_time => $in_seconds ) {                 // $is_end_time = 0 | 1

			if ( ! $is_end_time ) {

				if ( WPBC_FULL_DAY_TIME_IN == $in_seconds ) {           // situation: 00:00     e.g. 1 sec.
					$in_seconds = 0;
				} else {
					$in_seconds = $in_seconds - 10 - 1;
				}

			} else {

				if ( WPBC_FULL_DAY_TIME_OUT == $in_seconds ) {           // situation: 24:00     e.g. 86400 -10 +2 sec.
					$in_seconds = 86400;
				} else {
					$in_seconds = $in_seconds + 10 - 2;
				}
			}

			$just_minutes_as_seconds = $in_seconds % ( 60 * 60 );

			$in_hours   = ( $in_seconds - $just_minutes_as_seconds ) / ( 60 * 60 );                                     // 43200
			$in_minutes = $just_minutes_as_seconds / 60;                                                                // 43200

			$in_hours   = intval($in_hours);    // from 20.99 hours get 20          // round( $in_hours,   0, PHP_ROUND_HALF_DOWN );
			$in_minutes = intval($in_minutes);  // from 55.99 minutes get 55        // round( $in_minutes, 0, PHP_ROUND_HALF_DOWN );     // making 1.5 into 1 and -1.5 into -1.

			$in_hours   = ( $in_hours < 10 )   ? '0' . $in_hours   : $in_hours;
			$in_minutes = ( $in_minutes < 10 ) ? '0' . $in_minutes : $in_minutes;

			$time_slot[] = $in_hours . ':' . $in_minutes;
		}

		$time_slot = implode( ' - ', $time_slot );

		return $time_slot;
	}


	/**
	 * Get SQL TIME  from SECONDS       43211 -> '12:00:11'
	 *
	 * @param int $in_seconds   43201
	 *
	 * @return string       '10:00:02'
	 */
	function wpbc_transform__seconds__in__24_hours_his( $in_seconds ){

		$rest_without_hours_as_seconds = $in_seconds % ( 60 * 60 );

		$in_hours = ( $in_seconds - $rest_without_hours_as_seconds ) / ( 60 * 60 );                                     // 12
		$in_hours = intval( $in_hours );    // from 20.99 hours get 20          // round( $in_hours,   0, PHP_ROUND_HALF_DOWN );

		$in_minutes = $rest_without_hours_as_seconds / 60;                                                                // 43200
		$in_minutes = intval( $in_minutes );  // from 55.99 minutes get 55        // round( $in_minutes, 0, PHP_ROUND_HALF_DOWN );     // making 1.5 into 1 and -1.5 into -1.

		$in_only_seconds = $in_seconds - ( $in_hours * 60 * 60 ) - ( $in_minutes * 60 );                           // 43200
		$in_only_seconds = intval( $in_only_seconds );  // from 55.99 minutes get 55        // round( $in_minutes, 0, PHP_ROUND_HALF_DOWN );     // making 1.5 into 1 and -1.5 into -1.


		$in_hours        = ( $in_hours < 10 ) ? '0' . $in_hours : $in_hours;
		$in_minutes      = ( $in_minutes < 10 ) ? '0' . $in_minutes : $in_minutes;
		$in_only_seconds = ( $in_only_seconds < 10 ) ? '0' . $in_only_seconds : $in_only_seconds;

		$sql_time_his = $in_hours . ':' . $in_minutes . ':'. $in_only_seconds;

		return $sql_time_his;
	}


	/**
	 * Get time in seconds from  SQL time format                '12:00:02' -> 43192
	 *
	 * @param string $sql_time_his     '12:00:02'
	 *
	 * @return int
	 */
	function wpbc_transform__24_hours_his__in__seconds( $in_24_hours_his ) {

		$is_apply__check_in_out__10s = false;

		return wpbc_convert__time_his__to_seconds( $in_24_hours_his, $is_apply__check_in_out__10s );
	}

	/**
	 * Get AM/PM or 24 hour TIME  from SECONDS       43211 -> '12:00 PM'    |    86400 -> '12:00 AM'
	 *
	 * @param int $in_seconds           43201
	 * @param string $time_format      ''       (optional) time format, like 'H:i:s'  otherwise get from Booking > Settings General
	 *
	 * @return string                   '10:00:02' |  '10:00 AM'
	 */
	function wpbc_transform__seconds__in__formated_hours( $in_seconds, $time_format = '' ) {

		if ( empty( $time_format ) ) {
			$time_format = get_bk_option( 'booking_time_format' );          // get  from  Booking Calendar
			if ( empty( $time_format ) ) {
				$time_format = get_option( 'time_format' );                 // Get  WordPress default
			}
		}

		if ( $in_seconds >= 86400 ) {
			// if we have 24:00 then  instead of 00:00 show 24:00 ... Please check more here https://www.php.net/manual/en/datetime.format.php
			$time_format = str_replace( array( 'H', 'G' ), '24', $time_format );
			//$in_seconds--;  // It will decrees time on 1 second and show time as 11:59PM instead of 12:00AM
		}

		$s_tm = date_i18n( $time_format, $in_seconds );

		return $s_tm;
	}

	// -----------------------------------------------------------------------------------------------------------------


	/**
	 * Union 2 time-slot ranges:       "100 - 900" & "500 - 3500" -> [ "100 - 3500" ]  OR   "10 - 70" & "100 - 500" -> [ "10 - 70", "100 - 500" ]
	 *
	 * @param $timeslot_A_in_range_seconds '36011 - 86392'   it is means:  "'Start time1 in seconds' - 'End time1 in seconds'"  e.g.   "10:00 - 24:00"
	 * @param $timeslot_B_in_range_seconds '1 - 43192'       it is means:  "'Start time2 in seconds' - 'End time2 in seconds'"  e.g.   "00:00 - 12:00"
	 *
	 * @return array [ "1 - 86392" ]  one or two ranges
	 *
	 */
	function wpbc_union__timeslots_seconds( $timeslot_A_in_range_seconds, $timeslot_B_in_range_seconds ) {

		if ( ! wpbc_is__timeslots_seconds__intersected( $timeslot_A_in_range_seconds, $timeslot_B_in_range_seconds ) ) {
			return array( $timeslot_A_in_range_seconds, $timeslot_B_in_range_seconds );
		}

		if ( ( '0' == $timeslot_A_in_range_seconds ) || ( '0' == $timeslot_B_in_range_seconds ) ) {
			return array( '0 - 86400' );                                                                                // Old Full day booking, it is means always intersect.
		}

		$rangeA_arr = explode( '-', $timeslot_A_in_range_seconds );
		$rangeB_arr = explode( '-', $timeslot_B_in_range_seconds );

		$rangeA_arr[0] = intval( trim( $rangeA_arr[0] ) );
		$rangeA_arr[1] = intval( trim( $rangeA_arr[1] ) );
		$rangeB_arr[0] = intval( trim( $rangeB_arr[0] ) );
		$rangeB_arr[1] = intval( trim( $rangeB_arr[1] ) );

		$start  = min( $rangeA_arr[0], $rangeB_arr[0] );
		$end    = max( $rangeA_arr[1], $rangeB_arr[1] );
		$result = array( $start . ' - ' . $end );

		return $result;
	}


	/**
	 * Is 2 time-slots ranges intersected:       "36011 - 86392"    <=>    "1 - 43192"  =  true      ( intersected )
	 *
	 * Good explanation  here https://stackoverflow.com/questions/3269434/whats-the-most-efficient-way-to-test-if-two-ranges-overlap
	 *
	 * @param $timeslot_A_in_range_seconds '36011 - 86392'   it is means:  "'Start time1 in seconds' - 'End time1 in seconds'"  e.g.   "10:00 - 24:00"
	 * @param $timeslot_B_in_range_seconds '1 - 43192'       it is means:  "'Start time2 in seconds' - 'End time2 in seconds'"  e.g.   "00:00 - 12:00"
	 *
	 * @return bool
	 *
	 *
	 *   Some exceptions:
	 *                      if range = '0' - it is means Full  day  booking,  it's always intersected !
	 *    all start times ended with "1" second and previously was added +10 seconds, that's why 36011 is means 36011 - 10 - 1 = 36000  e.g. = 10:00
	 *    all end times ended with "2" second and previously was -10 seconds, that's why 43192 is means 43192 + 10 - 2 = 43200  e.g. = 12:00
	 *
	 *    When  in some date we have ONLY  start  time or end time,  it's means that this time start from  00:00 or end at  24:00  (because usually  such bookings for SEVERAL days)
	 *    and we autofill such  times by  adding start  time or end time:
	 *                                                                      Autofilled start time is always 1       = 0           +1     - 00:01
	 *                                                                      Autofilled end   time is always 86392   = 86400  -10  +2     - 23:59:58
	 */
	function wpbc_is__timeslots_seconds__intersected( $timeslot_A_in_range_seconds, $timeslot_B_in_range_seconds ) {

		// Full  day  booking,  it is means always intersect.
		if ( ( '0' == $timeslot_A_in_range_seconds ) || ( '0' == $timeslot_B_in_range_seconds ) ) {
			return true;                                                        // Time ranges INTERSECTED
		}

		$rangeA_arr = explode( '-', $timeslot_A_in_range_seconds );
		$rangeB_arr = explode( '-', $timeslot_B_in_range_seconds );

		$rangeA_arr[0] = intval( trim( $rangeA_arr[0] ) );
		$rangeA_arr[1] = intval( trim( $rangeA_arr[1] ) );
		$rangeB_arr[0] = intval( trim( $rangeB_arr[0] ) );
		$rangeB_arr[1] = intval( trim( $rangeB_arr[1] ) );


		$is_intersected = max( $rangeA_arr[0], $rangeB_arr[0] ) - min( $rangeA_arr[1], $rangeB_arr[1] );

		// if ( 0 == $is_intersected ) {
		//	                                 // Such ranges going one after other, e.g.: "12:00 - 15:00" and "15:00 - 21:00"
		// }

		if ( $is_intersected < 0 ) {
			return true;                     // Time ranges INTERSECTED
		}

		return false;                       // Otherwise time slot not intersected
	}


	/**
	 * Is 2 time-slots ranges intersected:       "10:00 - 24:00"    <=>    "00:00 - 12:00"  =  true      ( intersected )
	 *
	 *
	 * @param $timeslot_A_readable '10:00 - 24:00'
	 * @param $timeslot_B_readable '00:00 - 12:00'
	 *
	 * @return bool
	 *
	 *
	 *   See more here:     wpbc_is__timeslots_seconds__intersected()
	 */
	function wpbc_is__timeslots_readable__intersected( $timeslot_A_readable, $timeslot_B_readable ) {

		// Full  day  booking,  it is means always intersect.
		if ( ( '0' == $timeslot_A_readable ) || ( '0' == $timeslot_B_readable ) ) {
			return true;                                                        // Time ranges INTERSECTED
		}

		$timeslot_A_in_range_seconds = wpbc_convert__readable_time_slot__to__time_range_in_seconds( $timeslot_A_readable );
		$timeslot_B_in_range_seconds = wpbc_convert__readable_time_slot__to__time_range_in_seconds( $timeslot_B_readable );

		return wpbc_is__timeslots_seconds__intersected( $timeslot_A_in_range_seconds, $timeslot_B_in_range_seconds );
	}


	// -----------------------------------------------------------------------------------------------------------------

		/**
		 * Check if  BOOKING_FORM  time-slots     available and not intersect  with  booked time slots from  bookings
		 *
		 *
		 * @param array $checking__timerange_sec__arr [ '36011 - 43192', '56011 - 86392' ]
		 * @param array $booked__timerange_sec__arr   [ '36011 - 43192' ]
		 *
		 * @return bool                               true | false
		 *
		 *
		 *      if $checking__timerange_sec__arr EMPTY  then  TRUE
		 *
		 */
		function wpbc_is_some_timeslot__available__in_arr( $checking__timerange_sec__arr, $booked__timerange_sec__arr ) {

			if ( empty( $checking__timerange_sec__arr ) ) {
				return true;
			}

			$is_available__timeslots__arr = array();

			// Available_Form time-slots:  [ "10:00 - 12:00", "12:00 - 14:00", "14:00 - 16:00" ]
			foreach ( $checking__timerange_sec__arr as $checking__timeslot__key => $checking__timeslot__value ) {

				$is_available__timeslots__arr[ $checking__timeslot__key ] = true;

				// Booked time-slots:  [ "12:00 - 14:00", "14:00 - 16:00" ]
				foreach ( $booked__timerange_sec__arr as $booked__timeslot_value ) {

					$is_time_intersected = wpbc_is__timeslots_seconds__intersected( $booked__timeslot_value, $checking__timeslot__value );      // '36011 - 43192', '56011 - 86392'
					if ( $is_time_intersected ) {
						$is_available__timeslots__arr[ $checking__timeslot__key ] = false;
						break;
					}
				}
			}

			// If at least one time slot available then day still available
			$is_some_timeslot_available = false;
			foreach ( $is_available__timeslots__arr as $is__timeslot_available ) {
				if ( $is__timeslot_available ) {
					$is_some_timeslot_available = true;
					break;
				}
			}

			return $is_some_timeslot_available;
		}

	// -----------------------------------------------------------------------------------------------------------------

	/**
	 * '43211 - 86392'   into   [43201, 86400]
	 *
	 * @param string $booked_times__key_arr
	 * @param bool $is_apply_end_time_correction
	 *
	 * @return array|string[]
	 */
	function wpbc_transform_timerange__s_range__in__seconds_arr( $booked_times__key_arr, $is_apply_end_time_correction = true ){

		$booked_times__key_arr = explode( ' - ', $booked_times__key_arr );

		$booked_times__key_arr[0] = intval( trim( $booked_times__key_arr[0] ) );
		$booked_times__key_arr[1] = intval( trim( $booked_times__key_arr[1] ) );

		if ( $is_apply_end_time_correction ) {

			// Fix when  we have 10:00:11 seconds, and we need to  show the 14:00:02
			if ( '1' == substr( (string) $booked_times__key_arr[0], - 1 ) ) {
				$booked_times__key_arr[0] = $booked_times__key_arr[0] - 10;
			}
			$booked_times__key_arr[0] = ( $booked_times__key_arr[0] < 0 ) ? 1 : $booked_times__key_arr[0];

			// Fix when  we have 13:59:52 seconds, and we need to  show the 14:00:02
			if ( '2' == substr( (string) $booked_times__key_arr[1], - 1 ) ) {
				$booked_times__key_arr[1] = $booked_times__key_arr[1] + 10;
			}

			$booked_times__key_arr[1] = ( $booked_times__key_arr[1] > 86400 ) ? 86400 : $booked_times__key_arr[1];
		}

		return $booked_times__key_arr;
	}


	/**
	 * [43211, 86400] ->    '12:00:11 - 24:00:00'
	 *
	 * @param $booked_times__key_arr
	 *
	 * @return string
	 */
	function wpbc_transform_timerange__seconds_arr__in__24_hours_range( $booked_times__key_arr ){

		$readable_time_slot_formatted =  wpbc_transform__seconds__in__24_hours_his( $booked_times__key_arr[0] )
		                                . ' - '
		                                . wpbc_transform__seconds__in__24_hours_his( $booked_times__key_arr[1] ) ;

		return $readable_time_slot_formatted;
	}


	/**
	 * [43211, 86400] ->    '12:00 PM  - 12:00 AM'      -   transform  time-range       in      General Settings - Time Format
	 *
	 * @param $booked_times__key_arr
	 *
	 * @return string
	 */
	function wpbc_transform_timerange__seconds_arr__in__formated_hours( $booked_times__key_arr ){

		$readable_time_slot_formatted =  wpbc_transform__seconds__in__formated_hours( $booked_times__key_arr[0] )
		                                . ' - '
		                                . wpbc_transform__seconds__in__formated_hours( $booked_times__key_arr[1] ) ;

		return $readable_time_slot_formatted;
	}


	/**
	 * Converts a period of time in seconds into a human-readable format representing the interval.
	 *
	 * @param  int $time_interval_in_seconds    : 90    -   A period of time in seconds.
	 *
	 * @return string                           : '1 minute 30 seconds'
	 *
	 * Example:
	 *
	 *     echo wpbc_get_readable_time_interval( 90 );          <-  1 minute 30 seconds
	 *
	 */
	function wpbc_get_readable_time_interval( $time_interval_in_seconds ) {

		// Array of time period chunks.
		$chunks = array(
			/* translators: 1: The number of years in an interval of time. */
			array( 60 * 60 * 24 * 365, _n_noop( '%s year', '%s years', 'booking' ) ),
			/* translators: 1: The number of months in an interval of time. */
			array( 60 * 60 * 24 * 30, _n_noop( '%s month', '%s months', 'booking' ) ),
			/* translators: 1: The number of weeks in an interval of time. */
			array( 60 * 60 * 24 * 7, _n_noop( '%s week', '%s weeks', 'booking' ) ),
			/* translators: 1: The number of days in an interval of time. */
			array( 60 * 60 * 24, _n_noop( '%s day', '%s days', 'booking' ) ),
			/* translators: 1: The number of hours in an interval of time. */
			array( 60 * 60, _n_noop( '%s hour', '%s hours', 'booking' ) ),
			/* translators: 1: The number of minutes in an interval of time. */
			array( 60, _n_noop( '%s minute', '%s minutes', 'booking' ) ),
			/* translators: 1: The number of seconds in an interval of time. */
			array( 1, _n_noop( '%s second', '%s seconds', 'booking' ) ),
		);

		if ( ( $time_interval_in_seconds <= 0 ) || ( ! is_int( $time_interval_in_seconds ) ) ) {
			return __( 'now', 'booking' );
		}

		/**
		 * We only want to output two chunks of time here, eg:
		 * x years, xx months
		 * x days, xx hours
		 * so there's only two bits of calculation below:
		 */
		$j = count( $chunks );

		// Step one: the first chunk.
		for ( $i = 0; $i < $j; $i++ ) {
			$seconds = $chunks[ $i ][0];
			$name = $chunks[ $i ][1];

			// Finding the biggest chunk (if the chunk fits, break).
			$count = floor( $time_interval_in_seconds / $seconds );
			if ( $count ) {
				break;
			}
		}

		// Set output var.
		$output = sprintf( translate_nooped_plural( $name, $count, 'booking' ), $count );

		// Step two: the second chunk.
		if ( $i + 1 < $j ) {
			$seconds2 = $chunks[ $i + 1 ][0];
			$name2 = $chunks[ $i + 1 ][1];
			$count2 = floor( ( $time_interval_in_seconds - ( $seconds * $count ) ) / $seconds2 );
			if ( $count2 ) {
				// Add to output var.
				$output .= ' ' . sprintf( translate_nooped_plural( $name2, $count2, 'booking' ), $count2 );
			}
		}

		return $output;
	}


// =====================================================================================================================
//  ==  D A T E S   M a i n l y  ===
// =====================================================================================================================


/**
 * Conception:  - Time-Slots     A  - B                    '10:00:01 - 12:00:02'                 '10:00:01 - 12:00:02'
 *
 *              - Check in       A  - ...                  '14:00:01 -  ...  '                   '14:00:01 - 24:00:00'
 *              - Check out      ... -  B                  '  ...  - 12:00:02'                   '00:00:00 - 12:00:02'
 *
 *              - Full day       ... - ...                 '  ...  -  ...  '                     '00:00:00 - 24:00:00'
 *
 *              - Full IN       ..1 - ...                  '00:00:01 -  ...  '                   '00:00:01 - 24:00:00'
 *              - Full OUT       ... - ..2                 '  ...  - 24:00:02'                   '00:00:00 - 24:00:02'
 *
 *
 *              1) Always in one specific date,  can  be start & end times.
 *              2) Such  start  end times can  define
 *
 */

// ---------------------------------------------------------------------------------------------------------------------
// Support Transformation functions for dates arrays
// ---------------------------------------------------------------------------------------------------------------------

	/**
	 *  From SQL dates array  generate new Extended Dates Array:   [ > resource_id < ][ > booking_id < ] => Obj(  'sql__booking_dates__arr':[
	 *																												                            [ >seconds< ] =>       > SQL DATE <
	 *																												                            [1693303211]  => 2023-08-29 10:00:01
	 *																												                            [1693353600]  => 2023-08-30 00:00:00
	 *																												                            [1693483192]  => 2023-08-31 12:00:02
	 *																												                          ]
	 *																								            , ... )
	 * @param array $params = array [
	                                    'sql_dates_arr'      = [
																	 [0] => stdClass Object (
																            [booking_date] => 2023-08-08 10:00:01
																            [approved] => 1
																            [date_res_type] =>
																            [booking_id] => 45
																            [form] => selectbox-one^rangetime2^10:00 - 12:00~text^...
																            [parent] => 0
																            [prioritet] => 20
																            [type] => 2
																        )
																    [1] => stdClass Object (
																            [booking_date] => 2023-08-08 10:00:01
																            [approved] => 0
																            [date_res_type] =>
																            [booking_id] => 46
																            [form] => selectbox-one^rangetime10^10:00 - 12:00~text^...
																            [parent] => 2
																            [prioritet] => 1
																            [type] => 10
																        ), ...
														    , ...]
										, 'is_sort__dates_arr'          => true
										, 'is_apply__check_in_out__10s' => true
						            ]
	 *
	 * @return array =   [ > resource_id < ][ > booking_id < ] => obj( ... )

			Example:
				         [
								[3] = [
											[64] = obj{
														   booking_date = "2023-09-26 14:00:01"
														   approved = "0"
														   date_res_type = null
														   booking_id = "64"
														   form = "text^selected_short_dates_hint3^...
														   parent = "0"
														   prioritet = "30"
														   type = "3"
														   __summary__booking = [
																		        sql__booking_dates__arr = [  1695736811 = "2023-09-26 14:00:01"
																							       1695772800 = "2023-09-27 00:00:00"
																							       1695902392 = "2023-09-28 12:00:02"
											                                                    ]
											                                 ]
													  }
											[47] => stdClass Object(...)
											 ...
								       ]
							    ...
			            ]
	 *
	 *
	 *  Each such  booking is date object with  additional property:        -> __summary__booking[ 'sql__booking_dates__arr' ]
	 *  It is array of ALL Dates (in SQL date format) for specific booking
	 *  Then if needed, we extend booked dates   on specific number of times or hours/minutes
	 *
	 *
	 *   Relative this:   ['__summary__booking']['sql__booking_dates__arr'] = [
																	1695736811 = "2023-09-26 14:00:01"
																	1695772800 = "2023-09-27 00:00:00"
																	1695902392 = "2023-09-28 12:00:02"
																]
	 *                  '1695736811'  - timestamp of check in/out dates on 10 seconds less/higher than SQL date '2023-09-26 14:00:01'
	 *
	 */
	function wpbc_support__transform__into__resource_booking_dates__arr( $params ){

		$defaults = array(
		                  'sql_dates_arr'               => array()
						, 'is_sort__dates_arr'          => true
						, 'is_apply__check_in_out__10s' => true
					);
		$params   = wp_parse_args( $params, $defaults );


		$result_arr = array();

		foreach ( $params['sql_dates_arr'] as $date_object ) {

			$booking_id  = $date_object->booking_id;                                                                           // '43'
			$resource_id = ( ! empty( $date_object->date_res_type ) ) ? $date_object->date_res_type : $date_object->type;      // '12'

			if ( empty( $result_arr[ $resource_id ] ) ) {                   $result_arr[ $resource_id ] = array(); }
			if ( empty( $result_arr[ $resource_id ][$booking_id] ) ) {

				$result_arr[ $resource_id ][$booking_id] = $date_object;
				$result_arr[ $resource_id ][$booking_id]->__summary__booking = array(	'sql__booking_dates__arr' => array()   );     // New '__summary__booking' property
			}

			// Get seconds timestamp
			$in_seconds = wpbc_convert__sql_date__to_seconds( $date_object->booking_date, $params['is_apply__check_in_out__10s'] );

			$result_arr[ $resource_id ][ $booking_id ]->__summary__booking[ 'sql__booking_dates__arr' ][ $in_seconds ] = $date_object->booking_date;


			// Sort new array  with dates
			if ( $params['is_sort__dates_arr'] ) {
				ksort( $result_arr[ $resource_id ][ $booking_id ]->__summary__booking[ 'sql__booking_dates__arr' ] );
			}
		}

		return $result_arr;
	}


	/**
	 *  Transform Into:      ['2024-01-28'][ > resource_id < ][ > booking_id < ][ > only_time_seconds_int < ]  => obj(   booking_date: "2024-01-28 10:00:01", ... )
	 *
	 * @param array $params = [
	 *                          'is_apply__check_in_out__10s' => true
	 *                          'resource_booking_dates_arr'  => array = [ > resource_id < ][ > booking_id < ] => obj( ... )
	 *	                      ]
	 *
	 *   Example:
	 *
	 *	 $params['resource_booking_dates_arr'] = [
	 *													 [3] = [
	 *																 [64] = obj{
	 *																			    booking_date = "2023-09-26 14:00:01"
	 *																			    approved = "0"
	 *																			    date_res_type = null
	 *																			    booking_id = "64"
	 *																			    form = "text^selected_short_dates_hint3^...
	 *																			    parent = "0"
	 *																			    prioritet = "30"
	 *																			    type = "3"
	 *																			    __summary__booking = [
	 *																							         sql__booking_dates__arr = [  1695736811 = "2023-09-26 14:00:01"
	 *																												        1695772800 = "2023-09-27 00:00:00"
	 *																												        1695902392 = "2023-09-28 12:00:02"
	 *																                                                     ]
	 *																                                  ]
	 *																		   }
	 *																  [47] => stdClass Object(...)
	 *																  ...
	 *													        ]
	 *												     ...
	 *								             ]
	 *
	 * @return array  -  ['2024-01-28'][ > resource_id < ][ > booking_id < ][ > only_time_seconds < ]  => obj(   booking_date: "2024-01-28 10:00:01", ... )
	 *
	 *      Example:
	 *		result = [
	 *					2023-08-01 = [
	 *								    3 = [
	 *											   62 = [
	 *													    36011 = {stdClass}
	 *													    43192 = {
	 *																     booking_date = "2023-08-01 12:00:02"
	 *																     approved = "0"
	 *																     date_res_type = null
	 *																     booking_id = "62"
	 *																     form = "selectbox-multiple^rangetime3[]^10:00 - 12:00~...
	 *																     parent = "0"
	 *																     prioritet = "30"
	 *																     type = "3"
	 *																     __summary__booking = [
	 *																					      sql__booking_dates__arr = [
	 *																										       1690884011 = "2023-08-01 10:00:01"
	 *																										       1690891192 = "2023-08-01 12:00:02"
	 *																										  ]
	 *																					  ]
	 *															     }
	 *												    ]
	 *									    ]
	 *						    ]
	 *					2023-08-05 = [ ... ]
	 *				]
	 */
	function wpbc_support__transform__into__date_resource_booking_timesec__arr( $params ){

		$defaults = array(
			                  'resource_booking_dates_arr'  => array()
							, 'is_apply__check_in_out__10s' => true
					);
		$params   = wp_parse_args( $params, $defaults );


		$result__arr = array();
		foreach ( $params['resource_booking_dates_arr'] as $resource_id => $bookings_arr ) {

			foreach ( $bookings_arr as $booking_id => $booking_obj ) {

				$extended_dates_arr = ( isset( $booking_obj->__summary__booking['sql__booking_dates__arr__extended'] ) )
										? $booking_obj->__summary__booking['sql__booking_dates__arr__extended']
										: $booking_obj->__summary__booking['sql__booking_dates__arr'];

				foreach ( $extended_dates_arr as $extended_date_time_stamp => $extended_date_sql ) {

					$new_extended_date_obj = wpbc_clone_array_of_objects( $booking_obj );
					$new_extended_date_obj->booking_date = $extended_date_sql;

					list( $date_without_time, $only_time ) = explode( ' ', $new_extended_date_obj->booking_date );          // '2024-01-28',  '12:00:02'
					$seconds_int = wpbc_convert__time_his__to_seconds( $only_time, $params['is_apply__check_in_out__10s'] );                                         // 43202

					if ( ! isset( $result__arr[ $date_without_time ] ) ) {                                $result__arr[ $date_without_time ] = array(); }
					if ( ! isset( $result__arr[ $date_without_time ][ $resource_id ] ) ) {                $result__arr[ $date_without_time ][ $resource_id ] = array(); }
					if ( ! isset( $result__arr[ $date_without_time ][ $resource_id ][ $booking_id ] ) ) { $result__arr[ $date_without_time ][ $resource_id ][ $booking_id ] = array(); }

					$result__arr[ $date_without_time ][ $resource_id ][ $booking_id ][ $seconds_int ] = $new_extended_date_obj;
				}
			}
		}

		return $result__arr;
		/**
			2024-01-28 = [ > resource_id <
	                            12 => [ > booking_id <
		                                    43 => [ > seconds <
			                                            36001 =>    Obj[
																		    booking_date    = "2024-01-28 10:00:01"
																		    date_res_type   = null
																		    booking_id      = "43"
																		    approved        = "0"
																		    form            = "selectbox-one^rangetime12^10:00 - 12:00~text^..."
																		    parent          = "2"
																		    type            = "12"
																		    ...
				                                                        ]
			                                            43202 =>    Obj[
																	        type            = "12"
		 */
	}


	/**
	 * Transform Into:     ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ...
	 *
	 * @param array $params  [
	 *          'is_apply__check_in_out__10s'       => true
	 *          'date_resource_booking_timesec_arr' =>  [
	 *                                                       2023-08-01 = [
	 *                                                      			      3 = [
	 *                                                      						    62 = [
	 *                                                      								     36011 = {stdClass}
	 *                                                      								     43192 = {
	 *                                                                                                         booking_date = "2023-08-01 12:00:02"
	 *                                                                                                         approved = "0"
	 *                                                                                                         date_res_type = null
	 *                                                                                                         booking_id = "62"
	 *                                                                                                         form = "selectbox-multiple^rangetime3[]^10:00 - 12:00~...
	 *                                                                                                         parent = "0"
	 *                                                                                                         prioritet = "30"
	 *                                                                                                         type = "3"
	 *                                                                                                         __summary__booking = [
	 *                                                                                                         			            sql__booking_dates__arr = [
	 *                                                                                                         								          1690884011 = "2023-08-01 10:00:01"
	 *                                                                                                         								          1690891192 = "2023-08-01 12:00:02"
	 *                                                                                                         								        ]
	 *                                                                                                         			         ]
	 *                                                      										      }
	 *                                                      							     ]
	 *                                                      				     ]
	 *                                                      	     ]
	 *                                                       2023-08-05 = [ ... ]
	 *                                                  ]
	 *
	 * @return array    =  ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ...
	 *
	 *   Example:  [
				    [2023-08-08] => [
							            [2] => [
					                                [36011 - 86392] => stdClass Object (    [booking_date] => 2023-08-08 10:00:01          , .... )
				                                ]
			                            [10] => [
	                                                [36011 - 86392] => stdClass Object (    [booking_date] => 2023-08-08 10:00:01          , .... )
	                                             ]
				                    ]
				    [2023-08-09] => [
	                                    [2] => [
		                                            [0]             => stdClass Object (    [booking_date] => 2023-08-09 00:00:00, .... )
			                                    ]
										[10] => [
	                                                [36011 - 43192] => stdClass Object (    [booking_date] => 2023-08-30 12:00:02
		                                                                                    , ....
																							__summary__booking = [
																											     sql__booking_dates__arr = [
																																  1690884011 = "2023-08-01 10:00:01"
																																  1690891192 = "2023-08-01 12:00:02"
																							                                    ]
																							                  ]
			                                                                            )
			                                    ]
	                               ]
	              ]

	 */
	function wpbc_support__transform__into__date_resource_timesec_range__arr( $params ){

		$defaults = array(
			                  'date_resource_booking_timesec_arr'  => array()
							, 'is_apply__check_in_out__10s' => true
					);
		$params   = wp_parse_args( $params, $defaults );


		$result__arr = array();

		foreach ( $params[ 'date_resource_booking_timesec_arr' ] as $a_only_date => $a_resources_arr ) { // '2023-07-25' => array( resource_id   => bookings_arr )

			foreach ( $a_resources_arr as $a_resource_id => $a_bookings_arr ) {             //              1   => array( booking_id => times_arr )

				foreach ( $a_bookings_arr as $a_booking_id => $a_seconds_arr_in_1_booking ) {    //              10       => array ( second => stdObj( booking_date obj from DB )

					if ( ! isset( $result__arr[ $a_only_date ] ) ) {                   $result__arr[ $a_only_date ] = array(); }
					if ( ! isset( $result__arr[ $a_only_date ][ $a_resource_id ] ) ) { $result__arr[ $a_only_date ][ $a_resource_id ] = array(); }

					// Check all TIMES for  SAME  booking:
					$all_seconds_for_this_booking_arr = array();

					foreach ( $a_seconds_arr_in_1_booking as $a_second => $a_booking_obj ) {     //                      0 =>  stdObj( booking_date obj from DB )
						$all_seconds_for_this_booking_arr[] = $a_second;
					}

					/**
					 * [ 36011 ] -> '36011 - 86392'     |       [36011, 43192]  ->  '36011 - 43192'
					 *
					 * In case if we have only start time or end time for specific SAME Booking,  then we need to  fill  times:  .. - 10:00  or 14:00 - ..
					 */
					$all_seconds__key__time_range = wpbc__get_time_range__from_times_arr( $all_seconds_for_this_booking_arr );


					// For debugging only ! -------------------------------------------------------------------------------
					$test_unexpected = explode( '-', $all_seconds__key__time_range );
					if ( count( $test_unexpected ) > 2 ) {
						// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
						echo "WPBC. Unexpected situation. We have more than 2 times for the booking {$a_booking_id}: {$all_seconds__key__time_range}";
						debuge( '$a_only_date, $a_resource_id, $a_booking_id, $all_seconds_for_this_booking_arr', $a_only_date, $a_resource_id, $a_booking_id, $all_seconds_for_this_booking_arr, __FILE__, __LINE__ );
					}
					// For debugging only ! -------------------------------------------------------------------------------

					$result__arr[ $a_only_date ][ $a_resource_id ][ $all_seconds__key__time_range ] = $a_booking_obj;
				}
			}
		}

		return $result__arr;
	}


		/**
		 *  Transform [ 36011 ] -> '36011 - 86392'     |       [36011, 43192]  ->  '36011 - 43192'
		 *
		 * @param array $all_seconds_for_this_booking_arr   [ 36011 ]           [36011, 43192]
		 *
		 * @return string                                   '36011 - 86392'     '36011 - 43192'
		 */
		function wpbc__get_time_range__from_times_arr( $all_seconds_for_this_booking_arr ){

	        // In case if we have only start time or end time for specific SAME Booking,  then we need to  fill  times:  .. - 10:00  or 14:00 - ..
			if  ( 1 == count( $all_seconds_for_this_booking_arr ) )  {

				$seconds__this__booking   = $all_seconds_for_this_booking_arr[0];
				//$is_check_in_out__or_full = $seconds__this__booking % 10;                                                       // 1, 2  (not 0)

				$is_check_in_out__or_full = substr( ( (string) $seconds__this__booking ), -1 );                           // '1', '2'  (not '0')

				if ( '1' == $is_check_in_out__or_full ) {
					$all_seconds_for_this_booking_arr = array( $seconds__this__booking, WPBC_FULL_DAY_TIME_OUT );   // 24 hours  - 10 seconds + 2 seconds (2 sec. - because check  out)
				}
				if ( '2' == $is_check_in_out__or_full ) {
					$all_seconds_for_this_booking_arr = array( WPBC_FULL_DAY_TIME_IN, $seconds__this__booking );    // + 1 second (1 sex. - because check  in)
				}
			}

			if  ( count( $all_seconds_for_this_booking_arr ) > 2 )  {
				// Non standard situation ??? !!!
			}

			$all_seconds__key__time_range = implode( ' - ', $all_seconds_for_this_booking_arr );

			return $all_seconds__key__time_range;
		}



// ---------------------------------------------------------------------------------------------------------------------
// Get READABLE_DATES_ARR  & create WPBC_BOOKING_DATE   for each  bookings in   [ > resource_id < ][ > booking_id < ][ ... ]
// ---------------------------------------------------------------------------------------------------------------------

// GOOD
/**
 * Loop all Resources / Bookings  to set 'WPBC_BOOKING_DATE' Objects:  [ > resource_id < ][ > booking_id < ] => ['__summary__booking']['sql__booking_dates__arr']['_readable_dates'] = [ 2023-09-01: [ 0: "00:00:01 - 24:00:00" ] , ... ]
 *
 * @param $resources__booking_id__obj     =   [ > resource_id < ][ > booking_id < ] => obj( ... )
 *
 * @return $resources__booking_id__obj = [
 *                                          3 = [
 *                                                  62 = {stdClass}
 *                                                  63 = {
 *                                                          booking_date = "2023-09-01 00:00:00"
 *                                                          approved = "0"
 *                                                          date_res_type = null
 *                                                          booking_id = "63"
 *                                                          form = "text^selected_short_dates_hint3^September 1, 2023...
 *                                                          parent = "0"
 *                                                          prioritet = "30"
 *                                                          type = "3"
 *                                                          __summary__booking = [
 *                                                                              sql__booking_dates__arr = [
 *
 *                                              ....
 */
function wpbc__in_all_bookings__create_WPBC_BOOKING_DATE( $resources__booking_id__obj ){


	// [ > resource_id < ][ > booking_id < ] => obj(  ['__summary__booking']['sql__booking_dates__arr'] [  ... ,  [ ' >seconds< '] => ' > SQL DATE < ' , ...  ]  )
	foreach ( $resources__booking_id__obj as $resource_id => $bookings_arr ) {

		foreach ( $bookings_arr as $booking_id => $booking_obj ) {

			$readable_datestimeslots_arr = wpbc__get__readable_dates_arr__from_timestamp_arr( $booking_obj->__summary__booking[ 'sql__booking_dates__arr' ] );

			// New Dates Object     -       for this booking ID
			$boking_dates_obj = new WPBC_BOOKING_DATE( $readable_datestimeslots_arr );

			$resources__booking_id__obj[$resource_id][$booking_id]->__summary__booking[ '__dates_obj' ] = $boking_dates_obj;

			if ( $boking_dates_obj->is_debug ) {
				$resources__booking_id__obj[$resource_id][$booking_id]->__summary__booking[ '__dates_obj__24_hour_arr' ]    = $boking_dates_obj->loop_all_dates( 'get_times__as_24_hour_arr' );
				$resources__booking_id__obj[$resource_id][$booking_id]->__summary__booking[ '__dates_obj__seconds_arr' ]    = $boking_dates_obj->loop_all_dates( 'get_times__as_seconds_arr' );
				$resources__booking_id__obj[$resource_id][$booking_id]->__summary__booking[ '__dates_obj__timestamps_arr' ] = $boking_dates_obj->loop_all_dates( 'get_times__as_timestamps_arr' );
			}

		}
	}

	return $resources__booking_id__obj;
}


// =====================================================================================================================
// Transform SQL dates INTO  Readable time-slots by Dates
//
// All these below 5 functions required for transformation booked SQL dates:    [  1690884011 : "2023-08-01 10:00:01", ... ]
// Into  readable time slots by  dates:                                         [ '2023-08-01': [  "10:00:01 - 12:00:02"  ], '2023-08-05': [ "10:00:01 - 12:00:02"  ]  ]
// =====================================================================================================================

	// GOOD
	/**
	 * Transform SQL dates INTO  Readable time-slots by Dates.      Transform linear [ 1690884011 = "2023-08-01 10:00:01" , ... ]    ->   [ '2023-08-01': [  0: "10:00:01 - 12:00:02" ], '2023-08-05': [ 0:"10:00:01 - 12:00:02" ] ...]
	 *
	 * @param array $sql_dates_arr    [
	 *  										 1690884011 = "2023-08-01 10:00:01"
	 *	    									 1690891192 = "2023-08-01 12:00:02"
	 *                                           ...
	 *                                ]
	 *
	 * @return array
	 *                                [
	 *                                    2023-08-01 = [  0 = "10:00:01 - 12:00:02"  ]
	 *                                    2023-08-05 = [  0 = "10:00:01 - 12:00:02"  ]
	 *                                ]
	 *                         OR
	 *                                [
	 *                                    2023-09-01 = [  0 = "00:00:01 - 24:00:00"  ]
	 *                                    2023-09-03 = [  0 = "00:00:00 - 24:00:00"  ]
	 *                                    2023-09-14 = [  0 = "00:00:00 - 24:00:02"  ]
	 *                                ]
	 *
	 */
	function wpbc__get__readable_dates_arr__from_timestamp_arr( $sql_dates_arr ){

		// Full  Dates
		$is_all_dates_full = wpbc_is_all__fulldays__in_dates_arr( $sql_dates_arr );
		if ( $is_all_dates_full ) {
			$sql_dates_arr = wpbc__add_to__fulldays__check_in_out( $sql_dates_arr );
		}

		/**
		 * Convert timestamps to                ->   [   '2023-08-01' : [ 36011 = "10:00:01", 43192 = "12:00:02" ]     ,   '2023-08-05' : [...] ...   ]
		 */
		$times_arr___by_dates = wpbc__transform__timestamp_arr__in__times_by_dates__arr(  $sql_dates_arr );

		/**
		 * Convert to our concept times:        ->   [   '2023-08-01' : [  0 = "10:00:01 - 12:00:02"  ],    '2023-08-05' : [  0 = "10:00:01 - 12:00:02"  ]   ]
		 */
		$times_arr___by_dates = wpbc__transform__times_by_dates__in__readable_dates_arr(  $times_arr___by_dates );

		return $times_arr___by_dates;
	}


		// GOOD
		/**
		 * Convert times by dates:   [ '2023-08-01': [ 36011: "10:00:01", ... ] ... ]   ->   [ '2023-08-01': [  0: "10:00:01 - 12:00:02" ], '2023-08-05': [ 0:"10:00:01 - 12:00:02" ] ...]
		 *
		 * @param $times_arr___by_dates = [
		 *                                    2023-08-01 = [
		 *                                                   36001 = "10:00:01"
		 *                                                   43202 = "12:00:02"
		 *                                                 ]
		 *                                    2023-08-05 = [
		 *                                                   36001 = "10:00:01"
		 *                                                   43202 = "12:00:02"
		 *                                                 ]
		 *                                ]
		 *
		 * @return array
		 *                                [
		 *                                    2023-08-01 = [  0 = "10:00:01 - 12:00:02"  ]
		 *                                    2023-08-05 = [  0 = "10:00:01 - 12:00:02"  ]
		 *                                ]
		 *                         OR
		 *                                [
		 *                                    2023-09-01 = [  0 = "00:00:01 - 24:00:00"  ]
		 *                                    2023-09-03 = [  0 = "00:00:00 - 24:00:00"  ]
		 *                                    2023-09-14 = [  0 = "00:00:00 - 24:00:02"  ]
		 *                                ]
		 *
		 *
		 *
		 *
		 * from this:
		 *
		 *   $times_arr___by_dates = [
		 *                              2023-09-01 = [
		 *                                              1 = "00:00:01"
		 *                                           ]
		 *                              2023-09-03 = [
		 *                                              0 = "00:00:00"
		 *                                           ]
		 *                              2023-09-14 = [
		 *                                              86402 = "24:00:02"
		 *                                           ]
		 *                          ]
		 *      OR this:
		 *                          [
		 *                              2023-08-01 = [
		 *                                              36001 = "10:00:01"
		 *                                              43202 = "12:00:02"
		 *                                           ]
		 *                              2023-08-05 = [
		 *                                              36001 = "10:00:01"
		 *                                              43202 = "12:00:02"
		 *                                           ]
		 *                          ]
		 *              OR
		 *                          [
		 *                              2023-09-26 = [
		 *                                              50401 = "14:00:01"
		 *                                           ]
		 *                              2023-09-27 = [
		 *                                              0 = "00:00:00"
		 *                                           ]
		 *                              2023-09-28 = [
		 *                                              43202 = "12:00:02"
		 *                                           ]
		 *                          ]
		 *   INTO
		 *
		 *              - Time-Slots     A  - B                      '10:00:01 - 12:00:02'
		 *
		 *              - Check in       A  - ...                    '14:00:01 - 24:00:00'
		 *              - Check out      ... -  B                    '00:00:00 - 12:00:02'
		 *
		 *                  - Full day       ... - ...                   '00:00:00 - 24:00:00'
		 *
		 *                  - Full IN       ..1 - ...                    '00:00:01 - 24:00:00'
		 *                  - Full OUT       ... - ..2                   '00:00:00 - 24:00:02'
		 *
		 */
		function wpbc__transform__times_by_dates__in__readable_dates_arr( $times_arr___by_dates ) {


			foreach ( $times_arr___by_dates as $only_date_key => $times_arr ) {

				/**
				 *  Because it's dates_times from 1 booking, then in each date we have only 1 or 2 times.
				 */

				if ( 1 == count( $times_arr___by_dates[ $only_date_key ] ) ) {

					// One Loop only,  to  get  the $time_only_24hours value
					foreach ( $times_arr___by_dates[ $only_date_key ] as $time_only_seconds => $time_only_24hours ) {

						if ( '00:00:00' == $time_only_24hours ) {                                                       // Full Day

							$times_arr___by_dates[ $only_date_key ] = array( '00:00:00', '24:00:00' );

						} else if( '00:00:01' == $time_only_24hours ) {                                                 // Check In  ___ full day

							$times_arr___by_dates[ $only_date_key ] = array( '00:00:01', '24:00:00' );

						} else if( '24:00:02' == $time_only_24hours ) {                                                 // Check Out ___ full day

							$times_arr___by_dates[ $only_date_key ] = array( '00:00:00', '24:00:02' );
						} else {

							// Check in / out
							$is_check_in_out__or_full = substr( $time_only_24hours, -1 );                               // '1', '2'  (not '0')

							if ( '1' == $is_check_in_out__or_full ) {                                                    // Check In

								$times_arr___by_dates[ $only_date_key ] = array( $time_only_24hours, '24:00:00' );

							} else if ( '2' == $is_check_in_out__or_full ) {                                            // Check Out

								$times_arr___by_dates[ $only_date_key ] = array( '00:00:00', $time_only_24hours );

							} else {                                                                                    // Unexpected ?
								// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
								echo "WPBC. Unexpected data value: {$time_only_24hours} Timestamp ended with value different than: 1|2 for the day {$only_date_key} in one booking ";
							}

						}
					}
				}


				if ( 2 == count( $times_arr___by_dates[ $only_date_key ] ) ) {

					// Time slots       or already defined      check in / out      times
					$times_his_values = implode( ' - ', $times_arr___by_dates[ $only_date_key ] );

					$times_arr___by_dates[ $only_date_key ]   = array();
					$times_arr___by_dates[ $only_date_key ][] = $times_his_values;

				} else {

					// Something wrong ????  Check it.
					// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
					echo "WPBC. Unexpected data value. We have more than 2 time slots for single day {$only_date_key} in one booking ";
					debuge( $times_arr___by_dates, __FILE__, __LINE__ );
				}
			}

			return $times_arr___by_dates;
		}


		// GOOD
		/**
		 *  Transform linear [ 1690884011 = "2023-08-01 10:00:01" , ... ]    ->   [   '2023-08-01' : [ 36011 = "10:00:01", 43192 = "12:00:02", ... ]  , '2023-08-05' : [...] ...   ]
         *
		 * @param array $datetimestamps_datesql_arr [
		 *												1690884011 = "2023-08-01 10:00:01"
		 *												1690891192 = "2023-08-01 12:00:02"
		 *												1691229611 = "2023-08-05 10:00:01"
		 *												1691236792 = "2023-08-05 12:00:02"
		 *                                          ]
		 *
		 * @return array                    [
		 *										2023-08-01 = [
		 *													    36011 = "10:00:01"
		 *													    43192 = "12:00:02"
		 *										2023-08-05 = [
		 *													    36011 = "10:00:01"
		 *													    43192 = "12:00:02"
		 *                                  ]
		 */
		function wpbc__transform__timestamp_arr__in__times_by_dates__arr( $datetimestamps_datesql_arr ) {

			ksort( $datetimestamps_datesql_arr );

			$by_dates__timestamp_datesql__arr = array();

			foreach ( $datetimestamps_datesql_arr as $this_datetime_stamp => $this_date_sql ) {

				//    '2023-08-01'    '10:00:01'
				list( $only_day_sql, $only_time_sql ) = explode( ' ', $this_date_sql );

				$only_day_sql  = trim( $only_day_sql );                                                                     // '2023-08-01'
				$only_time_sql = trim( $only_time_sql );                                                                    // '10:00:01'

				if ( ! isset( $by_dates__timestamp_datesql__arr[ $only_day_sql ] ) ) {
					$by_dates__timestamp_datesql__arr[ $only_day_sql ] = array();                                           // [   '2023-08-01': []   ]
				}

				$only_time_in_sec = wpbc_convert__time_his__to_seconds( $only_time_sql, false );                            // 36001,            false <-  $is_apply__check_in_out__10s

				//                                  '2023-08-01'            36001            '10:00:01'
				$by_dates__timestamp_datesql__arr[ $only_day_sql ][ $only_time_in_sec ] = $only_time_sql;
			}

			return $by_dates__timestamp_datesql__arr;
		}


		// GOOD
		/**
		 * Add to  the first  and last  dates the check in/out times
		 *
		 * @param array $sql_dates_arr
		 *
		 * @return array $sql_dates_arr
		 */
		function wpbc__add_to__fulldays__check_in_out( $sql_dates_arr ){

			// Add check in/out to  first  and last  dates !
			$is_apply__check_in_out__10s = false;

			// EVEN if we have only 1 day,  it has to work! from
			$all_timestamps_arr = array_keys( $sql_dates_arr );


			// CHECK_IN date,  -  lowest timestamp:  -------------------------------------------------------------------
			$check_in_timestamp = min( $all_timestamps_arr );
			// Remove this date
			if ( isset( $sql_dates_arr[ $check_in_timestamp ] ) ) { unset( $sql_dates_arr[ $check_in_timestamp ] ); }

			// Add new date:             see definition  of                 WPBC_FULL_DAY_TIME_IN       <-      00:00:01
			$real__check_in__date_sql     = gmdate( 'Y-m-d', $check_in_timestamp ) . ' 00:00:01';
			$real__check_in_timestamp_new = wpbc_convert__sql_date__to_seconds( gmdate( 'Y-m-d', $check_in_timestamp ) . ' 00:00:01', $is_apply__check_in_out__10s );
			$sql_dates_arr[ $real__check_in_timestamp_new ]  = $real__check_in__date_sql;


			// CHECK_OUT date,  - highest timestamp:  ------------------------------------------------------------------
			$check_out_timestamp = max( $all_timestamps_arr );
			// Remove this date
			if ( isset( $sql_dates_arr[ $check_out_timestamp ] ) ) {
				unset( $sql_dates_arr[ $check_out_timestamp ] );
			}
			// Add new date:             see definition  of                 WPBC_FULL_DAY_TIME_OUT      <-      23:59:52
			$real__check_out__date_sql     = gmdate( 'Y-m-d', $check_out_timestamp ) . ' 24:00:02';
			$real__check_out_timestamp_new = wpbc_convert__sql_date__to_seconds( gmdate( 'Y-m-d', $check_out_timestamp ) . ' 23:59:52', $is_apply__check_in_out__10s );
			$sql_dates_arr[ $real__check_out_timestamp_new ] = $real__check_out__date_sql;

			// Sort such dates again, because we changed the order   ---------------------------------------------------
			ksort( $sql_dates_arr );

			return $sql_dates_arr;
		}


		// GOOD
		/**
		 * Check  if all  dates in array it is full  dates  e.g.   2023-07-25 00:00:00
		 * and not the check  in/out,  such  as 2023-07-25 12:00:02
		 *
		 * @param array $booking_sqldates_arr  [
		 *  										 1690884011 = "2023-08-01 10:00:01"
		 *	    									 1690891192 = "2023-08-01 12:00:02"
		 *                                           ...
		 *                                     ]
		 *
		 * @return bool
		 */
		function wpbc_is_all__fulldays__in_dates_arr( $booking_sqldates_arr ) {

			$is_all_dates_full = true;

			foreach ( $booking_sqldates_arr as $date_sql ) {

				$is_check_in_out__or_full = (string) $date_sql;
				$is_check_in_out__or_full = substr( $is_check_in_out__or_full, - 1 );                                   // '0', '1', '2' from   "2023-08-01 12:00:02"
				if ( '0' !== $is_check_in_out__or_full ) {
					$is_all_dates_full = false;
					break;
				}
			}

			return $is_all_dates_full;
		}

// =====================================================================================================================


/**
 * Convert  [ "2023-10-20", "2023-10-25", "2023-11-23" ]  -> [ '20.10.2023', '25.10.2023', '23.11.2023' ]
 *
 * @param $dates_arr__yyyy_mm_dd            [ "2023-10-20", "2023-10-25", "2023-11-23" ]
 *
 * @return []                               [ '20.10.2023', '25.10.2023', '23.11.2023' ]
 */
function wpbc_convert_dates_arr__yyyy_mm_dd__to__dd_mm_yyyy( $dates_arr__yyyy_mm_dd ) {

	$dates_arr__dd_mm_yyyy = array_map( function ( $value ) {
																$value_arr = explode( '-', $value );
																return ( count( $value_arr ) > 2 )
																		?  $value_arr[2] . '.' . $value_arr[1] . '.' . $value_arr[0]
																		: '';
															}
										, $dates_arr__yyyy_mm_dd );    // [ "2023-10-20", "2023-10-25", "2023-11-23" ]

	$dates_arr__dd_mm_yyyy = array_filter( $dates_arr__dd_mm_yyyy );                                                    // All entries of array equal to FALSE (0, '', '0' ) will be removed.
	return $dates_arr__dd_mm_yyyy;
}


/**
 * Convert  '20.10.2023, 25.10.2023, 23.10.2023'   ->   '2023-10-20,2023-10-23,2023-10-25'
 *
 * or even: '20.10.2023 - 23.10.2023'   ->   '2023-10-20,2023-10-21,2023-10-22,2023-10-23'
 *
 * @param $str_dates__dd_mm_yyyy            '20.10.2023, 25.10.2023, 23.10.2023'
 *
 * @return string                           '2023-10-20,2023-10-23,2023-10-25'
 */
function wpbc_convert_dates_str__dd_mm_yyyy__to__yyyy_mm_dd( $str_dates__dd_mm_yyyy ) {

	$str_dates__dd_mm_yyyy = str_replace( '|', ',', $str_dates__dd_mm_yyyy );       // Check  this for some old versions of plugin

	if ( strpos( $str_dates__dd_mm_yyyy, ' - ' ) !== false ) {                      // Recheck for any type of Range Days Formats
		$arr_check_in_out_dates = explode( ' - ', $str_dates__dd_mm_yyyy );
		$str_dates__dd_mm_yyyy  = wpbc_get_comma_seprated_dates_from_to_day( $arr_check_in_out_dates[0], $arr_check_in_out_dates[1] );
	}

	$dates_arr__dd_mm_yyyy = explode( ',', $str_dates__dd_mm_yyyy );                         // Create dates Array

	$dates_arr__yyyy_mm_dd = array_map( function ( $value ) {
																$value = trim( $value );
																$value_arr = explode( '.', $value );
																return ( count( $value_arr ) > 2 )
																		? $value_arr[2] . '-' . $value_arr[1] . '-' . $value_arr[0]
																		: '';
															}
										, $dates_arr__dd_mm_yyyy );    // [ '20.10.2023', '25.10.2023', '23.11.2023' ]
	$dates_arr__yyyy_mm_dd = array_filter( $dates_arr__yyyy_mm_dd );                                                    // All entries of array equal to FALSE (0, '', '0' ) will be removed.
	// Remove duplicates
	$dates_arr__yyyy_mm_dd = array_unique( $dates_arr__yyyy_mm_dd );

	// Sort Dates
	sort( $dates_arr__yyyy_mm_dd );

	$dates_str__yyyy_mm_dd = implode( ',', $dates_arr__yyyy_mm_dd );

	return $dates_str__yyyy_mm_dd;                                     // '2023-10-20,2023-10-23,2023-10-25'
}

