<?php

/**
 * @package com_spbooking
 * @author JoomShaper http://www.joomshaper.com
 * @copyright Copyright (c) 2010 - 2023 JoomShaper
 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
 */

// No Direct Access
defined('_JEXEC') or die('Resticted Aceess');

use Joomla\CMS\Factory;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Filesystem\File;
use Joomla\String\StringHelper;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Component\ComponentHelper;

class SpbookingHelper
{

	/**
	 * get Menu Item Id
	 * @param view string | @param params array
	 * @return mixed (string|boolean)
	 */
	public static function getItemId($view = '', $params = array())
	{
		$arr = array();
		$menuId = '';

		$db = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('m.params, m.id')->from($db->qn('#__menu', 'm'));
		$query->where('m.client_id = 0');

		// If no view given then return first mainmenu id
		if (empty($view))
		{
			$query->where($db->qn('m.menutype') . ' = ' . $db->q('mainmenu'));
			$query->order($db->qn('m.id') . ' ASC');

			if (Multilanguage::isEnabled())
			{
				$query->where($db->qn('m.language') . ' = ' . $db->q(Factory::getLanguage()->getTag()));
			}

			$db->setQuery($query);
			$menuId = $db->loadObject()->id;
		}
		else
		{
			$link = 'index.php?option=com_spbooking&view=' . $view;
			$query->where($db->qn('m.link') . ' LIKE ' . $db->q('%' . $link . '%'));

			if (Multilanguage::isEnabled())
			{
				$query->where($db->qn('m.language') . ' = ' . $db->q(Factory::getLanguage()->getTag()));
			}

			// Check if params given
			if (!empty($params))
			{
				$db->setQuery($query);
				$menus = $db->loadObjectList();

				// Check all the params are in the params columns of #__menu table
				foreach ($menus as $menu)
				{
					if (true === self::inParams($menu->params, $params))
					{
						$menuId = $menu->id;
						break;
					}
				}
			}
			else
			{
				$db->setQuery($query);
				$result = $db->loadObject();

				if (!empty($result))
				{
					$menuId = $result->id;
				}
			}
		}

		if (!empty($menuId))
		{
			// Return $menuId;
			return '&Itemid=' . $menuId;
		}

		return false;
	}

	/**
	 * check the given params within the menu params
	 * @param json | #__menu table's params json string
	 * @param params | user provided params array
	 * @return boolean
	 */
	private static function inParams($json, $params = array())
	{
		$arr = array();

		if (!empty($json) && is_string($json))
		{
			$arr = json_decode($json, true);
		}

		if (!empty($arr) && !empty($params))
		{
			if (count(array_intersect($params, $arr)) === count($params))
			{
				return true;
			}
		}

		return false;
	}

	public static function getCountry($country_code)
	{
		$countries_list = array('US' => 'United States','GB' => 'United Kingdom','AE' => 'United Arab Emirates','AF' => 'Afghanistan','AX' => 'Åland Islands','AL' => 'Albania','DZ' => 'Algeria','AS' => 'American Samoa','AD' => 'Andorra','AO' => 'Angola','AI' => 'Anguilla','AQ' => 'Antarctica','AG' => 'Antigua and Barbuda','AR' => 'Argentina','AM' => 'Armenia','AW' => 'Aruba','AU' => 'Australia','AT' => 'Austria','AZ' => 'Azerbaijan','BS' => 'Bahamas','BH' => 'Bahrain','BD' => 'Bangladesh','BB' => 'Barbados','BY' => 'Belarus','BE' => 'Belgium','BZ' => 'Belize','BJ' => 'Benin','BM' => 'Bermuda','BT' => 'Bhutan','BO' => 'Bolivia, Plurinational State of','BQ' => 'Bonaire, Sint Eustatius and Saba','BA' => 'Bosnia and Herzegovina','BW' => 'Botswana','BV' => 'Bouvet Island','BR' => 'Brazil','IO' => 'British Indian Ocean Territory','BN' => 'Brunei Darussalam','BG' => 'Bulgaria','BF' => 'Burkina Faso','BI' => 'Burundi','KH' => 'Cambodia','CM' => 'Cameroon','CA' => 'Canada','CV' => 'Cape Verde','KY' => 'Cayman Islands','CF' => 'Central African Republic','TD' => 'Chad','CL' => 'Chile','CN' => 'China','CX' => 'Christmas Island','CC' => 'Cocos (Keeling) Islands','CO' => 'Colombia','KM' => 'Comoros','CG' => 'Congo','CD' => 'Congo, the Democratic Republic of the','CK' => 'Cook Islands','CR' => 'Costa Rica','CI' => 'Côte d\'Ivoire','HR' => 'Croatia','CU' => 'Cuba','CW' => 'Curaçao','CY' => 'Cyprus','CZ' => 'Czech Republic','DK' => 'Denmark','DJ' => 'Djibouti','DM' => 'Dominica','DO' => 'Dominican Republic','EC' => 'Ecuador','EG' => 'Egypt','SV' => 'El Salvador','GQ' => 'Equatorial Guinea','ER' => 'Eritrea','EE' => 'Estonia','ET' => 'Ethiopia','FK' => 'Falkland Islands (Malvinas)','FO' => 'Faroe Islands','FJ' => 'Fiji','FI' => 'Finland','FR' => 'France','GF' => 'French Guiana','PF' => 'French Polynesia','TF' => 'French Southern Territories','GA' => 'Gabon','GM' => 'Gambia','GE' => 'Georgia','DE' => 'Germany','GH' => 'Ghana','GI' => 'Gibraltar','GR' => 'Greece','GL' => 'Greenland','GD' => 'Grenada','GP' => 'Guadeloupe','GU' => 'Guam','GT' => 'Guatemala','GG' => 'Guernsey','GN' => 'Guinea','GW' => 'Guinea-Bissau','GY' => 'Guyana','HT' => 'Haiti','HM' => 'Heard Island and McDonald Islands','VA' => 'Holy See (Vatican City State)','HN' => 'Honduras','HK' => 'Hong Kong','HU' => 'Hungary','IS' => 'Iceland','IN' => 'India','ID' => 'Indonesia','IR' => 'Iran, Islamic Republic of','IQ' => 'Iraq','IE' => 'Ireland','IM' => 'Isle of Man','IL' => 'Israel','IT' => 'Italy','JM' => 'Jamaica','JP' => 'Japan','JE' => 'Jersey','JO' => 'Jordan','KZ' => 'Kazakhstan','KE' => 'Kenya','KI' => 'Kiribati','KP' => 'Korea, Democratic People\'s Republic of','KR' => 'Korea, Republic of','KW' => 'Kuwait','KG' => 'Kyrgyzstan','LA' => 'Lao People\'s Democratic Republic','LV' => 'Latvia','LB' => 'Lebanon','LS' => 'Lesotho','LR' => 'Liberia','LY' => 'Libya','LI' => 'Liechtenstein','LT' => 'Lithuania','LU' => 'Luxembourg','MO' => 'Macao','MK' => 'Macedonia, the Former Yugoslav Republic of','MG' => 'Madagascar','MW' => 'Malawi','MY' => 'Malaysia','MV' => 'Maldives','ML' => 'Mali','MT' => 'Malta','MH' => 'Marshall Islands','MQ' => 'Martinique','MR' => 'Mauritania','MU' => 'Mauritius','YT' => 'Mayotte','MX' => 'Mexico','FM' => 'Micronesia, Federated States of','MD' => 'Moldova, Republic of','MC' => 'Monaco','MN' => 'Mongolia','ME' => 'Montenegro','MS' => 'Montserrat','MA' => 'Morocco','MZ' => 'Mozambique','MM' => 'Myanmar','NA' => 'Namibia','NR' => 'Nauru','NP' => 'Nepal','NL' => 'Netherlands','NC' => 'New Caledonia','NZ' => 'New Zealand','NI' => 'Nicaragua','NE' => 'Niger','NG' => 'Nigeria','NU' => 'Niue','NF' => 'Norfolk Island','MP' => 'Northern Mariana Islands','NO' => 'Norway','OM' => 'Oman','PK' => 'Pakistan','PW' => 'Palau','PS' => '"Palestine, State of"','PA' => 'Panama','PG' => 'Papua New Guinea','PY' => 'Paraguay','PE' => 'Peru','PH' => 'Philippines','PN' => 'Pitcairn','PL' => 'Poland','PT' => 'Portugal','PR' => 'Puerto Rico','QA' => 'Qatar','RE' => 'Réunion','RO' => 'Romania','RU' => 'Russian Federation','RW' => 'Rwanda','BL' => 'Saint Barthélemy','SH' => 'Saint Helena, Ascension and Tristan da Cunha','KN' => 'Saint Kitts and Nevis','LC' => 'Saint Lucia','MF' => 'Saint Martin (French part)','PM' => 'Saint Pierre and Miquelon','VC' => 'Saint Vincent and the Grenadines','WS' => 'Samoa','SM' => 'San Marino','ST' => 'Sao Tome and Principe','SA' => 'Saudi Arabia','SN' => 'Senegal','RS' => 'Serbia','SC' => 'Seychelles','SL' => 'Sierra Leone','SG' => 'Singapore','SX' => 'Sint Maarten (Dutch part)','SK' => 'Slovakia','SI' => 'Slovenia','SB' => 'Solomon Islands','SO' => 'Somalia','ZA' => 'South Africa','GS' => 'South Georgia and the South Sandwich Islands','SS' => 'South Sudan','ES' => 'Spain','LK' => 'Sri Lanka','SD' => 'Sudan','SR' => 'Suriname','SJ' => 'Svalbard and Jan Mayen','SZ' => 'Swaziland','SE' => 'Sweden','CH' => 'Switzerland','SY' => 'Syrian Arab Republic','TW' => 'Taiwan, Province of China','TJ' => 'Tajikistan','TZ' => 'Tanzania, United Republic of','TH' => 'Thailand','TL' => 'Timor-Leste','TG' => 'Togo','TK' => 'Tokelau','TO' => 'Tonga','TT' => 'Trinidad and Tobago','TN' => 'Tunisia','TR' => 'Turkey','TM' => 'Turkmenistan','TC' => 'Turks and Caicos Islands','TV' => 'Tuvalu','UG' => 'Uganda','UA' => 'Ukraine','UM' => 'United States Minor Outlying Islands','UY' => 'Uruguay','UZ' => 'Uzbekistan','VU' => 'Vanuatu','VE' => 'Venezuela, Bolivarian Republic of','VN' => 'Viet Nam','VG' => 'Virgin Islands, British','VI' => 'Virgin Islands, U.S.','WF' => 'Wallis and Futuna','EH' => 'Western Sahara','YE' => 'Yemen','ZM' => 'Zambia','ZW' => 'Zimbabwe');
		$country_code = strtoupper($country_code);

		return !empty($countries_list[$country_code]) ? $countries_list[$country_code] : $country_code;
	}

	public static function pluralize($amount, $singular, $plural)
	{
		$amount = (int) $amount;

		if ($amount <= 1)
		{
			return Text::_($singular);
		}

		return Text::_($plural);
	}

	private static function compare($k, $o)
	{
		return function ($a, $b) use ($k, $o) {
			if ($o == 0)
			{
				return $a->$k <= $b->$k ? -1 : +1;
			}

			return $a->$k <= $b->$k ? +1 : -1;
		};
	}

	public static function keysort($arr = array(), $key = 'id',  $order = 0)
	{

		$is_object = false;

		if (empty($arr))
		{
			$arr = array();
		}
		else
		{
			if (is_object($arr))
			{
				$arr = json_decode(json_encode($arr), true);
				$is_object = true;
			}
		}

		usort($arr, self::compare($key, $order));

		if ($is_object)
		{
			return json_decode(json_encode($arr));
		}

		return $arr;
	}

	/**
	 * format and render price with currency information
	 * @param price | price value
	 * @param currency | in which currency the price is shown
	 * @param format | currency format. short and long two format allowed
	 * @param position | position of the currency placed. Left and Right are two available options.
	 * @param allow_space | 1 for allow space between currency and price, 0 otherwise.
	 * @param decimal | Sets the number of decimal points.
	 * @param dec_point | Sets the separator for the decimal point.
	 * @param thousand_sep | Sets the thousands separator.
	 *
	 * @return price with format
	 */
	public static function formatPrice($price, $currency = null, $format = null, $position = null, $allow_space = false, $decimal = 0, $dec_point = '.', $thousands_sep=',')
	{
		$cParams = ComponentHelper::getParams('com_spbooking');

		if (!isset($price) || !is_numeric($price))
		{
			$price = 0;
		}

		$price = number_format($price, $decimal, $dec_point, $thousands_sep);

		if (empty($currency))
		{
			$currency = $cParams->get('currency', 'USD:$');
		}

		if (empty($format))
		{
			$format = $cParams->get('currency_type', 'short');
		}

		if (empty($position))
		{
			$position = $cParams->get('currency_position', 'left');
		}

		$price_string = '';
		$currency = explode(':', $currency, 2);

		if ($format == 'short')
		{
			$currency = "<span class='short-curr'>" . $currency[1] . "</span>";
		}
		else
		{
			$currency = "<span class='long-curr'>" . $currency[0] . "</span>";
		}

		if ($position == 'left')
		{
			if ($allow_space)
			{
				$price_string .= $currency . ' ' . $price;
			}
			else
			{
				$price_string .= $currency . $price;
			}
		}
		else
		{
			if ($allow_space)
			{
				$price_string .= $price . ' ' . $currency;
			}
			else
			{
				$price_string .= $price . $currency;
			}
		}

		return $price_string;
	}

	// Get item tags
	public static function getItemTags($tag_for = 'package', $ordering = 'DESC')
	{
		$db = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select($db->quoteName(array('id', 'title', 'alias')));
		$query->from($db->quoteName('#__spbooking_tags'));
		$query->where($db->quoteName('published') . " = 1");
		$query->where($db->quoteName('tag_for') . " = " . $db->quote($tag_for));
		$query->order($db->quoteName('ordering') . ' ' . $ordering);

		// Language filter
		if (Multilanguage::isEnabled())
		{
			$query->where($db->quoteName('language') . ' IN (' . $db->quote(Factory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		$db->setQuery($query);
		$results = $db->loadObjectList();

		return $results;
	}

	// Get item tags
	public static function getTagsInfo($tagids = array(), $view = 'packages', $ordering = 'DESC')
	{
		if (!empty($tagids))
		{
			$tagids = implode(',', json_decode($tagids));
			$db = Factory::getDbo();
			$query = $db->getQuery(true);
			$query->select($db->quoteName(array('id', 'title', 'alias')));
			$query->from($db->quoteName('#__spbooking_tags'));
			$query->where($db->quoteName('published') . " = 1");
			$query->where($db->quoteName('id') . " IN (" . $tagids . ")");
			$query->order($db->quoteName('ordering') . ' ' . $ordering);

			// Language filter
			if (Multilanguage::isEnabled())
			{
				$query->where($db->quoteName('language') . ' IN (' . $db->quote(Factory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
			}

			$db->setQuery($query);
			$results = $db->loadObjectList();

			foreach ($results as &$result)
			{
				$result->url = Route::_('index.php?option=com_spbooking&view=' . $view . '&tags=' . $result->id . '&searching=1' . self::getItemId($view));
			}

			return $results;
		}
		else
		{
			return array();
		}
	}

	// Get Places info by ids
	public static function getPlacesInfo($placeids = array(), $ordering = 'DESC')
	{

		if (!empty($placeids))
		{
			$placeids = implode(',', $placeids);
			$db = Factory::getDbo();
			$query = $db->getQuery(true);
			$query->select($db->quoteName(array('id', 'title', 'alias', 'image')));
			$query->from($db->quoteName('#__spbooking_places'));
			$query->where($db->quoteName('published') . " = 1");
			$query->where($db->quoteName('id') . " IN (" . $placeids . ")");

			// Language filter
			if (Multilanguage::isEnabled())
			{
				$query->where($db->quoteName('language') . ' IN (' . $db->quote(Factory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
			}

			$query->order($db->quoteName('ordering') . ' ' . $ordering);

			$db->setQuery($query);
			$items = $db->loadObjectList();

			foreach ($items as &$item)
			{
				$item->url = Route::_('index.php?option=com_spbooking&view=place&id=' . $item->id . ':' . $item->alias . self::getItemId('places'));
			}

			return $items;
		}
		else
		{
			return array();
		}

	}

	// Get additional services
	public static function getFacilities($for = 'accomodation', $ordering = 'DESC')
	{
		$db = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('a.title, a.id, a.price, a.max_quantity, a.description')
			->from($db->quoteName('#__spbooking_additionalservices', 'a'));

		$query->where($db->quoteName('a.service_for') . ' = ' . $query->quote($for));
		$query->where($db->quoteName('a.published') . ' = 1');

		// Language filter
		if (Multilanguage::isEnabled())
		{
			$query->where($db->quoteName('a.language') . ' IN (' . $db->quote(Factory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		$query->order($db->quoteName('a.ordering') . ' ' . $ordering);

		$db->setQuery($query);

		return $db->loadObjectList();
	}

	// Get categories
	public static function getCategories($for = 'transports', $ordering = 'DESC')
	{
		$db = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('a.id, a.title, a.description, a.icon_image, a.icon, a.image')
			->from($db->quoteName('#__spbooking_categories', 'a'));

		$query->where($db->quoteName('a.category_for') . ' = ' . $query->quote($for));
		$query->where($db->quoteName('a.published') . ' = 1');

		// Language filter
		if (Multilanguage::isEnabled())
		{
			$query->where($db->quoteName('a.language') . ' IN (' . $db->quote(Factory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		$query->order($db->quoteName('a.ordering') . ' ' . $ordering);

		$db->setQuery($query);

		return $db->loadObjectList();
	}


	public static function calculateReview($id, $review_for = 'accomodation')
	{

		// Declaration
		$cParams 	 = ComponentHelper::getParams('com_spbooking');
		$review_type = $cParams->get('review_type', 1);

		$rating_breakdown  = array_fill(0, 6, 0);
		$travellers_review = $average_traveller_review = self::getReviewOptions();

		if (empty($id))
		{
			return array(
				'average_rating' => 0,
				'total_reviews' => 1,
				'rating_breakdown' => array(),
				'traveller_review' => array(),
				'reviews' => array(),
				'average_traveller_review' => array()
			);
		}

		$conditions = array();

		$db    = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('a.*')
			->from($db->quoteName('#__spbooking_reviews', 'a'));

		if ($review_for == 'accomodation')
		{
			$conditions[] = $db->quoteName('a.accomodation_id') . ' = ' . $db->quote($id);
		}
		elseif ($review_for == 'package')
		{
			$conditions[] = $db->quoteName('a.package_id') . ' = ' . $db->quote($id);
		}
		elseif ($review_for == 'transport')
		{
			$conditions[] = $db->quoteName('a.transport_id') . ' = ' . $db->quote($id);
		}
		elseif ($review_for == 'place')
		{
			$conditions[] = $db->quoteName('a.place_id') . ' = ' . $db->quote($id);
		}

		$conditions[] = $db->quoteName('a.reviewed_for') . ' = ' . $db->quote($review_for);
		$conditions[] = $db->quoteName('a.published') . ' = 1';

		$query->where($conditions);
		$db->setQuery($query);
		$reviews = $db->loadObjectList();

		$review_avg    = 0;
		$total_reviews = 0;

		if (!empty($reviews))
		{
			$total_reviews = count($reviews);
			$review_count  = 0;

			foreach ($reviews as $review)
			{
				if (!empty($review->advance_rating) && is_string($review->advance_rating))
				{
					$review->advance_rating = json_decode($review->advance_rating, true);
				}

				if (!empty($review->advance_rating) && is_array($review->advance_rating))
				{
					$count = 0;

					foreach ($review->advance_rating as $key => $advr)
					{
						$count += (int) $advr;

						if (isset($travellers_review[$key]))
						{
							$travellers_review[$key] += (int) $advr;
							$average_traveller_review[$key] += 1;       // Count Average Traveler Review per review title
						}
					}

					$review_count += $count / 5;
				}

				$review->inner_rating = $count / 5;
				$review->inner_rating = number_format($review->inner_rating, 1);

				// Calculate rating for every star
				$rating_breakdown[round($review->inner_rating)]++;
			}

			$review_avg = $review_count / $total_reviews;
		}

		$reviews_copy = $reviews;
		$top_rating   = array();
		$top_rating   = self::keysort($reviews_copy, 'inner_rating', 1);
		$reviews 	  = self::keysort($reviews, 'created', 1);

		return array(
			'average_rating' => number_format($review_avg, 1),
			'total_reviews' => $total_reviews,
			'rating_breakdown' => $rating_breakdown,
			'traveller_review' => $travellers_review,
			'reviews' => $reviews,
			'top_rating' => $top_rating,
			'average_traveller_review' => $average_traveller_review
		);
	}

	/**
	 * Get Avaliable rooms
	 *
	 * @return $rooms info | accomodation_ ids
	 */
	public static function getAvailableRooms($checkin, $checkout, $accomodation = null, $number_of_rooms = 0, $adults = 1, $children = 0, $country = null, $city = null, $return_type = 0)
	{
		// Get all the rooms containing by the accomodation
		$db = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('a.*, b.title as accomodation, b.country, b.city')
			->from($db->quoteName('#__spbooking_rooms', 'a'))
			->join('LEFT', $db->quoteName('#__spbooking_accomodations', 'b') . ' ON(' . $db->quoteName('a.accomodation_id') . ' = ' . $db->quoteName('b.id') . ')');

		$conditions = array();

		if (!empty($country))
		{
			$conditions[] = $db->quoteName('b.country') . ' = ' . $db->quote(base64_decode($country));
		}

		if (!empty($city))
		{
			$conditions[] = $db->quoteName('b.city') . ' = ' . $db->quote(base64_decode($city));
		}

		if (!empty($accomodation))
		{
			$conditions[] = $db->quoteName('a.accomodation_id') . ' = ' . $db->quote($accomodation);
		}

		$conditions[] = $db->quoteName('a.adult') . ' >= ' . $adults;
		$conditions[] = $db->quoteName('a.child') . ' >= ' . $children;
		$conditions[] = $db->quoteName('a.published') . ' = 1';

		// Language filter
		if (Multilanguage::isEnabled())
		{
			$query->where($db->quoteName('a.language') . ' IN (' . $db->quote(Factory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		$query->where($conditions);
		$query->order($db->quoteName('a.created') . ' DESC');

		$db->setQuery($query);
		$rooms = $db->loadObjectList();
		unset($db, $query);

		// Get all the booking information within the checkin-out period
		if (!empty($checkin) && !empty($checkout))
		{
			$db = Factory::getDbo();
			$query = $db->getQuery(true);
			$query->select('a.*')
				->from($db->quoteName('#__spbooking_bookings', 'a'));

			// Check any of checkin, checkout date lay between #__spbooking_bookings table's checkin-checkout date range.
			// If so then the room is not available.
			$availablityquery = '(' . $db->quoteName('a.checkin') . ' <= ' . $db->quote($checkin) . ' AND ' . $db->quoteName('a.checkout') . ' > ' . $db->quote($checkin) . ') OR (' .
			$db->quoteName('a.checkin') . ' <= ' . $db->quote($checkout) . ' AND ' . $db->quoteName('a.checkout') . ' > ' . $db->quote($checkout) . ')';

			$query->where($availablityquery);
			$query->where($db->quoteName('a.published') . ' = 1');

			$db->setQuery($query);

			$bookings = $db->loadObjectList();
		}
		else
		{
			$bookings = array();
		}

		unset($db, $query);

		// Check all rooms and find how many rooms already booked.
		if (!empty($rooms))
		{
			foreach ($rooms as $room)
			{
				$room->booked = self::roomBooked($bookings, $room->id);
				$begin = DateTime::createFromFormat('Y-m-d', $checkin);
				$end = DateTime::createFromFormat('Y-m-d', $checkout);
				$interval = DateInterval::createFromDateString('1 day');
				$period = new DatePeriod($begin, $interval, $end);

				foreach ($period as $pr)
				{
					$room->c_price[] = self::calculatePriceForDay($room->id, $pr->format('Y-m-d'));
				}

				if (!empty($room->c_price))
				{
					$s_sum    = 0;
					$c_sum    = 0;
					$ch_sum   = 0;
					$ch_s_sum = 0;
					$non_discount_day = 0;
					$non_discount_day_price = 0;
					$child_non_discount_day = 0;
					$child_non_discount_day_price = 0;

					foreach ($room->c_price as $cprice)
					{
						if ($cprice['special_price'] === 0)
						{
							$non_discount_day++;
							$non_discount_day_price += (float) $cprice['original_price'];
						}

						if ($cprice['child_special_price'] === 0)
						{
							$child_non_discount_day++;
							$child_non_discount_day_price += (float) $cprice['child_price'];
						}

						$s_sum    += (float) $cprice['special_price'];
						$c_sum    += (float) $cprice['original_price'];
						$ch_sum   += (float) $cprice['child_price'];
						$ch_s_sum += (float) $cprice['child_special_price'];
					}

					// If the discounted days passed away between the selected day’s intervals.
					if ($non_discount_day !== count($room->c_price))
					{
						$s_sum = $non_discount_day_price + $s_sum;
					}

					if ($child_non_discount_day !== count($room->c_price))
					{
						$ch_s_sum = $child_non_discount_day_price + $ch_s_sum;
					}

					$room->special_avg_price  = round($s_sum / count($room->c_price));
					$room->original_avg_price = round($c_sum / count($room->c_price));
					$room->child_avg_price	  = round($ch_sum / count($room->c_price));
					$room->child_special_avg_price = round($ch_s_sum / count($room->c_price));
				}
			}
		}

		// Check available rooms
		$aids = array();

		if (!empty($rooms))
		{
			foreach ($rooms as $v)
			{
				$room_numbers = explode(',', $v->room_number);
				$total_rooms = 0;

				if (!empty($room_numbers))
				{
					$total_rooms = count($room_numbers);
				}

				if ((int) $v->booked < $total_rooms)
				{
					$v->available_rooms = $total_rooms - $v->booked;

					if ($v->available_rooms >= $number_of_rooms && !in_array($v->accomodation_id, $aids))
					{
						$aids[] = $v->accomodation_id;
					}
				}
				else
				{
					$v->available_rooms = 0;
				}
			}
		}

		if ($return_type == 0)
		{
			return $rooms;
		}
		else
		{
			return $aids;
		}
	}

	private static function roomBooked($bookings, $room_id)
	{
		$count = 0;

		if (!empty($bookings))
		{
			foreach ($bookings as $booking)
			{
				if (!empty($booking->number_of_rooms) && is_string($booking->number_of_rooms))
				{
					$rooms_decode = json_decode($booking->number_of_rooms);

					foreach ($rooms_decode as $v)
					{
						if ($v->room == $room_id)
						{
							$count += (int) $v->norooms;
						}
					}
				}
			}
		}

		return $count;
	}

	public static function calculatePriceForDay($room_id, $date)
	{
		$price 			= 0;
		$sp_price 		= 0;
		$child_sp_price = 0;
		$date = new DateTime($date);
		$dayname = strtolower($date->format('D'));

		if (empty($room_id))
		{
			return $price;
		}

		$db = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('a.id, a.price, a.special_price,a.add_child_price,a.child_price')
			->from($db->quoteName('#__spbooking_rooms', 'a'))
			->where(
				array(
				$db->quoteName('a.id') . ' = ' . $db->quote($room_id),
				$db->quoteName('a.published') . ' = 1'
				)
			);

		// Language filter
		if (Multilanguage::isEnabled())
		{
			$query->where($db->quoteName('a.language') . ' IN (' . $db->quote(Factory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		$db->setQuery($query);
		$room = $db->loadObject();

		if (!empty($room->price) && is_string($room->price))
		{
			$room->price = json_decode($room->price);
		}

		if (!empty($room->special_price) && is_string($room->special_price))
		{
			$room->special_price = json_decode($room->special_price);
		}

		if ($room->add_child_price && !empty($room->child_price) && is_string($room->child_price))
		{
			$room->child_price = json_decode($room->child_price);
		}

		if (!empty($date))
		{
			if (!empty($room->special_price))
			{
				foreach ($room->special_price as $sp)
				{
					$start = new DateTime($sp->start_date);
					$end = new DateTime($sp->end_date);

					if ($date->getTimestamp() >= $start->getTimestamp() && $date->getTimestamp() <= $end->getTimestamp())
					{
						$sp_price 		= ($sp->special_price) ? $sp->special_price : 0;
						$child_sp_price = ($sp->child_special_price) ? $sp->child_special_price : 0;
						break;
					}
				}
			}
		}

		$return = array(
			'special_price'  	  => $sp_price,
			'child_special_price' => $child_sp_price,
			'original_price' 	  => $room->price->$dayname,
			'child_price'	 	  => (($room->add_child_price)) ? $room->child_price->$dayname : 0,
			'date' 				  => $date->format('Y-m-d')
		);

		return $return;
	}

	public static function isAvailableRoom($rooms, $room_id, $nrooms = 1, $adult = 1, $child = 0)
	{
		foreach ($rooms as $room)
		{
			if ($room->id == $room_id && $room->available_rooms >= $nrooms && $room->adult >= $adult && $room->child >= $child)
			{
				return true;
			}
		}

		return false;
	}

	// Check json string
	public static function checkIsJson($string)
	{
		json_decode($string);

		return (json_last_error() == JSON_ERROR_NONE);
	}

	public static function getCategory($category_for = 'accomodation')
	{
		$db = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('*')->from($db->quoteName('#__spbooking_categories'))
			->where($db->quoteName('category_for') . ' = ' . $db->quote($category_for))
			->where($db->quoteName('published') . ' = 1');

		// Language filter
		if (Multilanguage::isEnabled())
		{
			$query->where($db->quoteName('language') . ' IN (' . $db->quote(Factory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		$db->setQuery($query);

		return $db->loadObjectList();
	}

	public static function getThumbs($image, $thumb_size, $default)
	{
		$params = ComponentHelper::getParams('com_spbooking');
		$thumb 	= $params->get($thumb_size, $default);

		$filename 		= basename($image);
		$customizePath 	= JPATH_BASE . '/' . dirname($image) . '/thumbs/' . File::stripExt($filename) . '_' . $thumb . '.' . File::getExt($filename);
		$imageSrc		= Uri::base(true) . '/' . dirname($image) . '/thumbs/' . File::stripExt($filename) . '_' . $thumb . '.' . File::getExt($filename);

		if (File::exists($customizePath))
		{
			return $imageSrc;
		}

		return Uri::root() . $image;
	}

	public static function numberToWord( $num = 0, $currecny = "USD",  $allow_only = false)
	{
		if (empty($num))
		{
			$ret = "none";

			if ($allow_only)
			{
				$ret .= " " . $currecny . " Only";
			}

			return $ret;
		}

		$ones = array( 0 => "zero",  1 => "one",  2 => "two",  3 => "three",  4 => "four",  5 => "five",  6 => "six",  7 => "seven",  8 => "eight",  9 => "nine",  10 => "ten",  11 => "eleven",  12 => "twelve",  13 => "thirteen",  14 => "fourteen",  15 => "fifteen",  16 => "sixteen",  17 => "seventeen",  18 => "eighteen",  19 => "nineteen");
		$tens = array(  0 => "zero", 1 => "ten", 2 => "twenty", 3 => "thirty",  4 => "forty",  5 => "fifty",  6 => "sixty",  7 => "seventy",  8 => "eighty",  9 => "ninety" );
		$hundreds = array( "hundred", "thousand", "million", "billion", "trillion", "quardrillion" );

		$num = number_format($num, 2, ".", ",");
		$num_arr = explode(".", $num);
		$wholenum = $num_arr[0];
		$decnum = $num_arr[1];
		$whole_arr = array_reverse(explode(",", $wholenum));
		krsort($whole_arr, 1);
		$rettxt = "";

		foreach ($whole_arr as $key => $i)
		{
			while (substr($i, 0, 1) == "0")
			{
				$i = substr($i, 1, 5);
			}

			if (!empty($i))
			{
				if ($i < 20)
				{
					$rettxt .= $ones[$i];
				}
				elseif ($i < 100)
				{
					if (substr($i, 0, 1) != "0")
					{
						$rettxt .= $tens[substr($i, 0, 1)];
					}

					if (substr($i, 1, 1) != "0")
					{
						$rettxt .= " " . $ones[substr($i, 1, 1)];
					}
				}
				else
				{
					if (substr($i, 0, 1) != "0")
					{
						$rettxt .= $ones[substr($i, 0, 1)] . " " . $hundreds[0];
					}

					if (substr($i, 1, 1) != "0")
					{
						$rettxt .= " " . $tens[substr($i, 1, 1)];
					}

					if (substr($i, 2, 1) != "0")
					{
						$rettxt .= " " . $ones[substr($i, 2, 1)];
					}
				}
			}

			if ($key > 0)
			{
				$rettxt .= " " . $hundreds[$key] . " ";
			}
		}

		if ($decnum > 0)
		{
			$rettxt .= " and ";

			if ($decnum < 20)
			{
				$rettxt .= $ones[$decnum];
			}
			elseif ($decnum < 100)
			{
				$rettxt .= $tens[substr($decnum, 0, 1)];
				$rettxt .= " " . $ones[substr($decnum, 1, 1)];
			}
		}

		if ($allow_only)
		{
			$rettxt .= " " . $currecny . ' Only';
		}

		return $rettxt;
	}


	/**
	 * Return Review Options
	 *
	 * @param   array  $default_data		Default review options.
	 * @return array
	 * @since  2.1.0
	 */
	public static function getReviewOptions($default_data = null)
	{

		$cparams   = ComponentHelper::getParams('com_spbooking');
		$newRating = $cparams->get('new_rating');
		$newRatingFields = $cparams->get('new_rating_fields');

		$defaultReviewCategories = array(
			'safty_security' => 0,
			'maintenance' => 0,
			'cleanliness' => 0,
			'service' => 0,
			'hospitality' => 0
		);

		$defaultReviewCategories = (is_array($default_data) && $default_data) ? $default_data : $defaultReviewCategories;

		$newReviewCategories = array();

		if (is_object($newRatingFields) && $newRating)
		{
			foreach ($newRatingFields as $value)
			{
				if (empty(trim($value->rating_title)))
				{
					return $defaultReviewCategories;
				}

				$key = StringHelper::str_ireplace(' ', '_', $value->rating_title);
				$newReviewCategories[$key] = (is_array($default_data) && $default_data) ? $value->rating_title : 0;
			}

			return $newReviewCategories;
		}

		return $defaultReviewCategories;
	}
}
