window.hbfwc = window.hbfwc || {};
hbfwc.forms  = function ($) {
	const { __, _x, _n, _nx, sprintf } = wp.i18n;
	const forms = {
		init: function () {
			const d = this;

			if ( ! $('body').hasClass('single-product') ) {
				return;
			}

			d.calInit();
			d.convertNumberFields();
			d.addonInputs();

			$( window ).on(
				'load',
				function () {
					d.calInit();
				}
			);
		},
		calInit: function () {
			const d  = this;
			const wr = $( '#hbfwc-date-form-compact' );
			const df = wr.data( 'output-format' );
			const fr = $( '#hbfwc-cart' );

			if ( wr.length < 1 ) {
				return;
			}

			let checkoutOnlyDates = new Array();

			d.appendAlert();

			let al = $( '#hbfwc-alert-min-stay' );
			let cl = $( '#hbfwc-alert-only-checkout' );

			$( '#hbfwc-cart #children' ).trigger( 'change' );

			moment.suppressDeprecationWarnings = true;
			wr.daterangepicker(
				{
					opens: 'center',
					showDropdowns: false,
					autoUpdateInput: false,
					startDate: wr.find( 'input[name="check-in"]' ).val(),
					endDate: wr.find( 'input[name="check-out"]' ).val(),
					minDate: wr.data( 'mindate' ),
					locale: {
						format: 'MM/DD/YYYY',
						daysOfWeek: hbfwc.cal_string.locale.daysOfWeek,
						monthNames: hbfwc.cal_string.locale.monthNames
					},
					isCustomDate: function(date) {
						const currDate = moment(date).format('YYYY-MM-DD');

						if (hbfwc.invalid_dates.includes(currDate)) {
							const yesterday = moment(date).subtract(1, 'day').format('YYYY-MM-DD');

							if (hbfwc.invalid_dates.includes(yesterday)) {
								return ['full-disabled'];
							} else {
								return ['checkout-only'];
							}
						}

						return ['full-enabled'];
					},
					isInvalidDate: function(e) {
						if ( hbfwc.invalid_dates.length < 1 ){
							return false;
						}

						var currDate = moment(e._d).format('YYYY-MM-DD');
						var yesterday = new Date(currDate);
						yesterday.setDate(yesterday.getDate() - 1);
						
						if ( $.inArray( currDate, hbfwc.invalid_dates ) > -1  ) {
							var datestring = yesterday.getFullYear()  + "-" + ( (yesterday.getMonth()+1) > 10 ? (yesterday.getMonth()+1) : '0'+(yesterday.getMonth()+1) ) + "-" + yesterday.getDate();

							if ( $.inArray( datestring, hbfwc.invalid_dates ) > -1 ) {
								return true;
							} else {
								var picker = wr.data( 'daterangepicker' );

								var sel = new Date( picker.startDate.format( 'YYYY-MM-DD' ) );
								var til = new Date( currDate );

								if ( sel > til ) {
									return true;
								}

								var maybeInvalid = false;

								while(sel < til){
									var selstring = sel.getFullYear()  + "-" + ( (sel.getMonth()+1) > 10 ? (sel.getMonth()+1) : '0'+(sel.getMonth()+1) ) + "-" + sel.getDate();
									if ( $.inArray( selstring, hbfwc.invalid_dates ) > -1 ) {
										maybeInvalid = true;
										break;
									}

									sel.setDate(sel.getDate() + 1);
								}

								! maybeInvalid && ! checkoutOnlyDates.includes(currDate) && checkoutOnlyDates.push(currDate);

								return maybeInvalid;
							}
						}
						return false;
					},
					autoApply: true,
					showCancel: false,
				}
			);

			wr.on(
				'apply.daterangepicker',
				function (ev, picker) {
					const unixCi = picker.startDate.format('MM/DD/YYYY');
					const unixCo = picker.endDate.format('MM/DD/YYYY');

					const start = picker.startDate.clone();
					const end = picker.endDate.clone();
					const current = start.clone();
					const noOfNights = moment( end ).diff( moment( start ), "days" );

					let isValid = true;
					let message = '';

					if ( noOfNights < parseInt(wr.data( 'min-stay' )) ) {
						picker.setEndDate(start);
						if (picker.element && picker.element.is('input')) {
							picker.element.val('');
						}
						wr.trigger( 'click' );
						$( 'td.start-date' ).trigger( 'mouseover' );
						return;
					}

					while (current < end) {
						const dateStr = current.format('YYYY-MM-DD');

						if (hbfwc.invalid_dates.includes(dateStr)) {
							if (!checkoutOnlyDates.includes(dateStr) || dateStr !== picker.endDate.format('YYYY-MM-DD')) {
								isValid = false;
								message = __( "The room is not available on " + d.dateFormat( df, current.format( 'MM/DD/YYYY' ) ), 'hotel-booking-for-woocommerce' );
								break;
							}
						}
						current.add(1, 'day');
					}

					if (!isValid) {
						picker.setEndDate(start);

						if (picker.element && picker.element.is('input')) {
							picker.element.val('');
						}
						wr.trigger( 'click' );

						window.setTimeout( function() {
							var popup = $('<div class="hbfwc-checkout-popup">'+ message +'</div>');

							$('.daterangepicker').prepend(popup);

							popup.css({
								top: -popup.outerHeight() - 10,
								left: ( $('.daterangepicker').outerWidth() / 2 ) - ( popup.outerWidth() / 2 ),
							}).hide().fadeIn(150);
						}, 100);

						return;
					}

					$( this ).find( 'input[name="check-in"]' ).val( unixCi ).trigger( 'change' );
					$( this ).find( 'input[name="check-out"]' ).val( unixCo ).trigger( 'change' );
					$( this ).find( '.hbfwc-outputdate.check-in' ).text( d.dateFormat( df, unixCi) );
					$( this ).find( '.hbfwc-outputdate.check-out' ).text( d.dateFormat( df, unixCo ) );

					d.updateRates();
				}
			).on('show.daterangepicker', function(ev, picker) {
				$('.hbfwc-checkout-popup').remove();
				$('.showme').removeClass('showme');
			}).on('hide.daterangepicker', function(ev, picker) {
				$('.showme').removeClass('showme');
			});

			wr.data( 'daterangepicker' ).container.find('.drp-calendar').on('mousedown.daterangepicker', 'td.available', function() {
				$('.hbfwc-checkout-popup').remove();
				var picker = wr.data( 'daterangepicker' );
				var start = picker.startDate;
				var end = picker.endDate;
				var startFormatted = start.format('YYYY-MM-DD');

				if (!end || end.isSame(start)) {
					if (checkoutOnlyDates.includes(startFormatted)) {
						picker.setStartDate( wr.find( 'input[name="check-in"]' ).val() );
						picker.setEndDate( wr.find( 'input[name="check-out"]' ).val() );

						var popup = $('<div class="hbfwc-checkout-popup">'+ __( 'This date is only available for checkout.', 'hotel-booking-for-woocommerce' ) +'</div>');

						$('.daterangepicker').prepend(popup);

						popup.css({
							top: -popup.outerHeight() - 10,
							left: ( $('.daterangepicker').width() / 2 ) - ( popup.width() / 2 ),
						}).hide().fadeIn(150);
					}
				}
			})

			$( document.body ).on(
				'change',
				'input[name="check-in"], input[name="check-out"]',
				function () {
					const ci = moment( $( 'input[name="check-in"]' ).val(), 'MM/DD/YYYY' );
					const co = moment( $( 'input[name="check-out"]' ).val(), 'MM/DD/YYYY' );

					let noOfNights = co.diff( ci, "days" );
					let num        = $( '<span class="num" />' );
					let night      = $( '<span class="num-text" />' );

					num.text( noOfNights );
					night.text( noOfNights === 1 
						? $( '.night-totals' ).data( 'singular-unit' ) 
						: $( '.night-totals' ).data( 'plural-unit' ) 
					);

					$( '.night-totals' ).html( '' ).append( num ).append( night );
				}
			).on(
				'change',
				'input[name="rate"]',
				function() {
					const hasClassSel = $(this).closest('ul#hbfwc_rate_plans').find('li.rate-selected');
					hasClassSel.removeClass('rate-selected');
					$('input[name="rate"]:checked').closest('li.room-rate-option').addClass('rate-selected');
				}
			).on(
				'change',
				'#hbfwc-cart #qty',
				function () {
					d.inputAdjustmentvalue( '#adults', $( this ).val() );
					d.inputAdjustmentvalue( '#children', $( this ).val() );
					d.updateRates();
				}
			).on(
				'mouseover',
				'td.start-date',
				function () {
					const td  = this;
					const pos = {
						left: $( td ).offset().left - ((al.outerWidth() / 2) - ($( td ).outerWidth() / 2)),
						top: $( td ).offset().top - (al.outerHeight() + 8)
					}
					al.css( {left: pos.left, top: pos.top} );
					al.addClass( 'showme' );
				}
			).on(
				'mouseleave',
				'td.start-date',
				function () {
					al.removeClass( 'showme' );
				}
			).on(
				'mouseover',
				'td.checkout-only',
				function () {
					const td  = this;
					const pos = {
						left: $( td ).offset().left - ((cl.outerWidth() / 2) - ($( td ).outerWidth() / 2)),
						top: $( td ).offset().top - (cl.outerHeight() + 8)
					}
					cl.css( {left: pos.left, top: pos.top} );
					cl.addClass( 'showme' );
				}
			).on(
				'mouseleave',
				'td.checkout-only',
				function () {
					cl.removeClass( 'showme' );
				}
			).on(
				'change',
				'#hbfwc-cart #children',
				function (e) {
					const _t    = this;
					const vlnow = parseInt( $( this ).val() );

					if ( $( '#hhbfwc-children-age-slider__' + (vlnow + 1) ).length ) {
						$( '#hhbfwc-children-age-slider__' + (vlnow + 1) ).remove();
					}

					if ( vlnow < 1 ) {
						return false;
					}

					for (var i = 1; i <= vlnow; i++) {
						if ( $( '#hhbfwc-children-age-slider__' + i ).length < 1 ) {
							let chtemp = $( '#hbfwc-children-age-slider-template' ).html();
							chtemp     = chtemp.replaceAll( '{{number}}', i );
							$( chtemp ).appendTo( $( _t ).closest( '.hbfwc-fieldset' ) );
						}
					}
				}
			).on(
				'click',
				'.hbfwc-button__rate-popup',
				function (e) {
					e.preventDefault();
					const rate_id = $( this ).data( 'rate_id' );

					$( '#hbfwc-rate-popup-' + rate_id ).addClass( 'is_called' );
					$( '#hbfwc-rate-popup-' + rate_id ).attr('tabindex', '-1');
					setTimeout(() => $( '#hbfwc-rate-popup-' + rate_id ).focus(), 300);
				}
			).on(
				'click',
				'.hbfwc-rate__popup-close',
				function (e) {
					e.preventDefault();
					$( this ).closest( '.hbfwc-rate__popup' ).removeClass( 'is_called' );
				}
			).on(
				'click',
				'.hbfwc-rate__popup',
				function (e) {
					if ( ! e.target.closest( '.hbfwc-rate__popup-wrapper' ) ) {
						e.preventDefault();
						$( this ).find( '.hbfwc-rate__popup-close' ).trigger( 'click' );
					}
				}
			).on(
				'click',
				'.hbfwc-info-indicator',
				function (e) {
					e.preventDefault();
				}
			);
		},
		inputAdjustmentvalue: function (id, qty) {
			const origMax = $( id ).data( 'max-per-room' );

			if ( '' === origMax ) {
				return false;
			}

			const maxNow = parseInt( qty ) * parseInt( origMax );
			const curVal = $( id ).val();

			$( id ).attr( 'max',maxNow );
			if ( parseInt( curVal ) > maxNow ) {
				$( id ).val( maxNow )
			}
		},
		updateRates: function () {
			const url = new URL(window.location.href);

			// reset search params.
			url.search = "";

			// re-add search params
			url.searchParams.set('checkin', $('input[name="check-in"]').val());
			url.searchParams.set('checkout', $('input[name="check-out"]').val());
			url.searchParams.set('qty', $('#qty').val());
			if ( $('input[name="rate"]:checked').length ) {
				url.searchParams.set('rate', $('input[name="rate"]:checked').val());
			}
			url.searchParams.set('nocache', Date.now()); // cache buster.

			$('#hbfwc-cart').addClass('hbfwc-ajax-load');

			$('#hbfwc_rate_plans').load(
				url.toString() + " #hbfwc_rate_plans>*",
				function () {
					$('#hbfwc-cart').removeClass('hbfwc-ajax-load');
					$('#hbfwc-cart').find('input[name="rate"]').length < 1
						? $('#hbfwc-cart').find('button[name="add-to-cart"]').prop('disabled', true)
						: $('#hbfwc-cart').find('button[name="add-to-cart"]').prop('disabled', false);
				}
			);
		},
		appendAlert: function () {
			const [temp, cotemp] = [ $( '#hbfwc-alert-min-stay-template' ).html(), $('#hbfwc-alert-only-checkout-template').html() ];
			
			$('#hbfwc-alert-min-stay').length < 1 && $( temp ).appendTo( 'body' );
			$('#hbfwc-alert-only-checkout').length < 1 && $( cotemp ).appendTo( 'body' );
		},
		convertNumberFields: function () {
			const d            = this;
			const inputNumbers = $( "input.hbfgwc-with-buttons" );

			inputNumbers.each(
				function () {
					const t = $(this);
					const isDisabled = t.is(':disabled');

					if ( t.hasClass('converted') ) return;

					t.addClass('converted');

					t.wrap('<div class="hbfgwc-quantity-number"></div>');

					const $minus = $('<button type="button" class="hbfwc-minus-button">&ndash;</button>').insertBefore(t);
					const $plus  = $('<button type="button" class="hbfwc-plus-button">&plus;</button>').insertAfter(t);

					$minus.prop('disabled', isDisabled);
					$plus.prop('disabled', isDisabled);
				}
			);

			$( document.body ).on(
				'click',
				'.hbfwc-minus-button, .hbfwc-plus-button',
				function (e) {
					e.preventDefault();
					let inputNum = $( e.target ).parent().find( "input[type='number']" );
					if ( inputNum.is(':disabled') ) {
						return false;
					}
					$( this ).hasClass( 'hbfwc-minus-button' ) ? inputNum[0].stepDown() : inputNum[0].stepUp();
					inputNum.trigger( 'change' );
				}
			);
		},
		addonInputs: function() {
			const d = this;
			const toggleQty = ($parent, $checkbox) => {
				const match = $checkbox.attr('name').match(/\[(\d+)\]/);
				if (!match) return;

				const id = match[1];
				const $qtyInput = $parent.find(`input[name="addon_qty[${id}]"]`);

				if (!$qtyInput.length) return;

				const isChecked = $checkbox.is(':checked');

				// Enable/disable input.
				$qtyInput.prop('disabled', !isChecked).focus();

				// Enable/disable plus-minus buttons.
				const $wrapper = $qtyInput.closest('.hbfgwc-quantity-number');
				$wrapper.find('.hbfwc-minus-button, .hbfwc-plus-button').prop('disabled', !isChecked);
			};

			$('.hbfwc-single-addon-item').each(function() {
				const $parent = $(this);
				const $checkbox = $parent.find('input[type="checkbox"][name^="addon["]');

				if ($checkbox.length) {
					// Set initial state.
					toggleQty($parent, $checkbox);

					// Bind change event.
					$checkbox.on('change', function() {
						toggleQty($parent, $checkbox);
					});
				}
			});
		},
		dateFormat: function (format,date) {
			if ( ! date || date === "") {
				date = new Date();
			} else if (typeof('date') !== 'object') {
				date = new Date( date.replace( /-/g,"/" ) ); // attempt to convert string to date object
			}

			var string = '',
				mo     = date.getMonth(),   // month (0-11)
				m1     = mo + 1,			    // month (1-12)
				dow    = date.getDay(),    // day of week (0-6)
				d      = date.getDate(),     // day of the month (1-31)
				y      = date.getFullYear(), // 1999 or 2003
				h      = date.getHours(),    // hour (0-23)
				mi     = date.getMinutes(), // minute (0-59)
				s      = date.getSeconds();  // seconds (0-59)

			for (var i = 0, len = format.length; i < len; i++) {
				switch (format[i]) {
					case 'j': // Day of the month without leading zeros  (1 to 31)
						string += d;
						break;

					case 'd': // Day of the month, 2 digits with leading zeros (01 to 31)
						string += (d < 10) ? "0" + d : d;
						break;

					case 'l': // (lowercase 'L') A full textual representation of the day of the week
						var days = hbfwc.cal_string.date_l;
						string  += days[dow];
						break;

					case 'w': // Numeric representation of the day of the week (0=Sunday,1=Monday,...6=Saturday)
						string += dow;
						break;

					case 'D': // A textual representation of a day, three letters
						days    = hbfwc.cal_string.date_D;
						string += days[dow];
						break;

					case 'm': // Numeric representation of a month, with leading zeros (01 to 12)
						string += (m1 < 10) ? "0" + m1 : m1;
						break;

					case 'n': // Numeric representation of a month, without leading zeros (1 to 12)
						string += m1;
						break;

					case 'F': // A full textual representation of a month, such as January or March
						var months = hbfwc.cal_string.date_F;
						string    += months[mo];
						break;

					case 'M': // A short textual representation of a month, three letters (Jan - Dec)
						months  = hbfwc.cal_string.date_M;
						string += months[mo];
						break;

					case 'Y': // A full numeric representation of a year, 4 digits (1999 OR 2003)
						string += y;
						break;

					case 'y': // A two digit representation of a year (99 OR 03)
						string += y.toString().slice( -2 );
						break;

					case 'H': // 24-hour format of an hour with leading zeros (00 to 23)
						string += (h < 10) ? "0" + h : h;
						break;

					case 'g': // 12-hour format of an hour without leading zeros (1 to 12)
						var hour = (h === 0) ? 12 : h;
						string  += (hour > 12) ? hour - 12 : hour;
						break;

					case 'h': // 12-hour format of an hour with leading zeros (01 to 12)
						hour    = (h === 0) ? 12 : h;
						hour    = ( hour > 12) ? hour - 12 : hour;
						string += (hour < 10) ? "0" + hour : hour;
						break;

					case 'a': // Lowercase Ante meridiem and Post meridiem (am or pm)
						string += (h < 12) ? "am" : "pm";
						break;

					case 'i': // Minutes with leading zeros (00 to 59)
						string += (mi < 10) ? "0" + mi : mi;
						break;

					case 's': // Seconds, with leading zeros (00 to 59)
						string += (s < 10) ? "0" + s : s;
						break;

					case 'c': // ISO 8601 date (eg: 2012-11-20T18:05:54.944Z)
						string += date.toISOString();
						break;

					default:
						string += format[i];
				}
			}

			return string;
		}
	}
	forms.init();
	return forms;
}( window.jQuery );