/home/crealab/cars.brainware.com.co/wp-content/plugins/jet-booking/assets/js/admin/bookings.js
(function () {

	"use strict";

	const eventHub = new Vue();
	const { __, sprintf } = wp.i18n;
	const buildQuery = function ( params ) {
		return Object.keys( params ).map( function ( key ) {
			return key + '=' + params[ key ];
		} ).join( '&' );
	}

	window.jetBookingState = {
		isActive: false
	};

	const getCurrentMode = function () {
		let mode = window.location.hash ? window.location.hash.replace( '#', '' ) : false;

		if ( ! mode ) {
			return 'all';
		}

		return [ 'all', 'upcoming', 'past' ].includes( mode ) ? mode : 'all';
	}

	const statusMixin = {
		computed: Vuex.mapState( ['statuses_schema'] ),
		methods: {
			isFinished: function ( status ) {
				return ( 0 <= this.statuses_schema.finished.indexOf( status ) );
			},
			isInProgress: function ( status ) {
				return ( 0 <= this.statuses_schema.in_progress.indexOf( status ) );
			},
			isInvalid: function ( status ) {
				return ( 0 <= this.statuses_schema.invalid.indexOf( status ) );
			},
			statusClass: function ( status ) {
				return {
					'notice': true,
					'notice-alt': true,
					'notice-success': this.isFinished( status ),
					'notice-warning': this.isInProgress( status ),
					'notice-error': this.isInvalid( status )
				}
			},
		}
	};

	const itemsMethods = {
		computed: Vuex.mapState( [ 'bookings', 'bookings_units' ] ),
		methods: {
			getItemLabel: function ( item_id ) {
				return this.bookings[ item_id ] || item_id;
			},
			getItemUnitLabel: function ( item_id, unit_id ) {
				if ( this.bookings_units[ item_id ] && this.bookings_units[ item_id ][ unit_id] ) {
					return this.bookings_units[ item_id ][ unit_id ] + ' (#' + unit_id + ')';
				} else {
					return unit_id;
				}
			},
			getOrderLink: function ( orderID ) {
				return window.JetABAFConfig.edit_link.replace( /\%id\%/, orderID );
			}
		},
	}

	// Mixin for handling booking fields.
	const fieldsManager = {
		computed: Vuex.mapState( {
			bookingItem: 'bookingItem',
			dateRangePickerConfig: 'dateRangePickerConfig',
			isDisabled: 'isDisabled',
			itemUnits: 'itemUnits',
			bookingPrice: 'bookingPrice'
		} ),
		methods: {
			initDateRangePicker: function () {
				let self = this;

				store.dispatch( 'getDateRangePickerConfig' ).then( function () {
					jQuery( self.$refs.jetABAFDatePicker ).dateRangePicker( self.dateRangePickerConfig )
						.bind( 'datepicker-first-date-selected', () => {
							window.jetBookingState.isActive = true;
						} ).bind( 'datepicker-change', () => {
							window.jetBookingState.isActive = false;
						} );
				} );
			},
			getBookingPrice: function ( booking ) {
				jQuery.ajax( {
					url: window.JetABAFConfig.ajax_url,
					type: 'POST',
					dataType: 'json',
					data: {
						action: 'jet_booking_product_get_total_price',
						booking: booking,
						nonce: window?.JetABAFConfig?.nonce
					},
				} ).done( function ( response ) {
					store.commit( 'setValue', {
						key: 'bookingPrice',
						value: response.data.price
					} );
				} ).fail( function ( _, _2, errorThrown ) {
					alert( errorThrown );
				} );
			},
			beVisible: function ( key ) {
				switch ( key ) {
					case 'booking_id':
					case 'apartment_unit':
					case 'order_id':
					case 'user_id':
					case 'import_id':
					case 'status':
					case 'apartment_id':
					case 'check_in_date':
					case 'check_in_date_timestamp':
					case 'check_out_date':
					case 'check_out_date_timestamp':
						return false;
					default:
						return true;
				}
			},
			onApartmentChange: function () {
				this.initDateRangePicker();
			},
		}
	};

	const store = new Vuex.Store( {
		state: {
			...window.JetABAFConfig,
			pageUrl: new URL( window.location.href ),
			perPage: 15,
			offset: 0,
			pageNumber: 1,
			totalItems: 0,
			itemsList: [],
			isLoading: true,
			overlappingBookings: false,
			bookingItem: {},
			bookingPrice: 0,
			dateRangePickerConfig: {},
			isDisabled: false,
			itemUnits: [],
			currentFilters: {},
			sortBy: {
				orderby: 'booking_id',
				order: 'DESC'
			},
			currentView: 'list',
			views: {
				list: {
					label: __('List', 'jet-booking')
				},
				calendar: {
					label: __('Calendar', 'jet-booking')
				},
				timeline: {
					label: __('Timeline', 'jet-booking')
				},
			}
		},
		mutations: {
			setValue ( state, varObject ) {
				state[ varObject.key ] = varObject.value;
			},
		},
		actions: {
			getItems: function () {

				store.commit( 'setValue', {
					key: 'isLoading',
					value: true
				} );

				wp.apiFetch( {
					method: 'get',
					path: window.JetABAFConfig.api.bookings_list + '?' + buildQuery( {
						per_page: 'list' === store.state.currentView ? store.state.perPage : -1,
						offset: 'list' === store.state.currentView ? store.state.offset : 0,
						filters: JSON.stringify( store.state.currentFilters ),
						sort: JSON.stringify( store.state.sortBy ),
						mode: getCurrentMode(),
						view: store.state.currentView
					} ),
				} ).then( function ( response ) {

					store.commit( 'setValue', {
						key: 'isLoading',
						value: false
					} );

					if ( response.success ) {
						store.commit( 'setValue', {
							key: 'itemsList',
							value: response.data
						} );

						store.commit( 'setValue', {
							key: 'totalItems',
							value: +response.total
						} );
					}

				} ).catch( function ( e ) {

					store.commit( 'setValue', {
						key: 'isLoading',
						value: false
					} );

					eventHub.$CXNotice.add( {
						message: e.message,
						type: 'error',
						duration: 7000,
					} );

				} );

			},
			getDateRangePickerConfig: async function () {

				store.commit( 'setValue', {
					key: 'isDisabled',
					value: true
				} );

				const bookingItem = store.state.bookingItem;

				if ( ! bookingItem.check_in_date ) {
					bookingItem.check_in_date = '';
				}

				if ( ! bookingItem.check_out_date ) {
					bookingItem.check_out_date = '';
				}

				await wp.apiFetch( {
					method: 'post',
					path: window.JetABAFConfig.api.booked_dates,
					data: { item: bookingItem }
				} ).then( function ( response ) {
					if ( ! response.success ) {
						eventHub.$CXNotice.add( {
							message: response.data,
							type: 'error',
							duration: 7000,
						} );
					} else {
						const {
							per_nights: perNights,
							booked_dates: excludedDates,
							booked_next: excludedNext,
							disabled_days: disabledDays,
							check_in_days: checkInDays,
							checkout_only: checkoutOnly,
							labels: labels,
							start_day_offset: startDayOffset,
							end_date: rangeEndDate,
							min_days: minDays,
							max_days: maxDays,
							month_select: monthSelect,
							year_select: yearSelect
						} = response;

						window.JetABAFConfig = { ...window.JetABAFConfig, ...response };

						if ( bookingItem.check_in_date.length && bookingItem.check_out_date.length && 0 <= excludedDates.indexOf( bookingItem.check_in_date ) ) {
							let deleteCount = moment( bookingItem.check_out_date ).diff( moment( bookingItem.check_in_date ), 'days' );

							if ( ! perNights ) {
								deleteCount++;
							}

							excludedDates.splice( excludedDates.indexOf( bookingItem.check_in_date ), deleteCount );
							excludedDates.push( ...response.days_off )
						}

						let config = {
							autoClose: true,
							separator: ' - ',
							startDate: new Date(),
							startOfWeek: response.start_of_week,
							getValue: function () {
								if ( bookingItem.check_in_date && bookingItem.check_out_date ) {
									return bookingItem.check_in_date + ' - ' + bookingItem.check_out_date;
								} else {
									return '';
								}
							},
							setValue: function ( s, s1, s2 ) {
								if ( s === s1 ) {
									s2 = s1;
								}

								bookingItem.check_in_date = s1;
								bookingItem.check_out_date = s2;
							},
							minDays: minDays.length && +minDays ? +minDays : '',
							maxDays: maxDays.length && +maxDays ? +maxDays : '',
							perNights: perNights,
							container: '.jet-abaf-details__booking-dates',
							beforeShowDay: function ( t ) {
								const formatted = moment( t ).format('YYYY-MM-DD');

								let valid = true,
									_class = '',
									_tooltip = '';

								if ( disabledDays.length && 0 <= disabledDays.indexOf( t.getDay() ) ) {
									const disabledNext = moment( t ).add( 1, 'd' ).format('YYYY-MM-DD');

									if ( ! ( 0 <= excludedNext.indexOf( disabledNext ) ) ) {
										excludedNext.push( disabledNext );
									}

									if ( ! ( 0 <= excludedDates.indexOf( formatted ) ) ) {
										excludedDates.push( formatted );
									}

									valid = false;
								}

								if ( checkInDays.length && -1 === checkInDays.indexOf( t.getDay() ) ) {
									valid = window.jetBookingState.isActive && -1 === disabledDays.indexOf( t.getDay() );
								}

								if ( excludedDates.length && 0 <= excludedDates.indexOf( formatted ) ) {
									valid = false;
									_tooltip = response.custom_labels ? labels.booked : __( 'Sold out', 'jet-booking' );

									// Mark first day of booked period as checkout only
									if ( checkoutOnly ) {
										let next = moment( t ).add( 1, 'd' ).format('YYYY-MM-DD'),
											prev = moment( t ).subtract( 1, 'd' ).format('YYYY-MM-DD');

										if ( 0 <= excludedNext.indexOf( next ) || ( 0 <= excludedDates.indexOf( next ) && -1 === excludedDates.indexOf( prev ) ) ) {
											if ( window.jetBookingState.isActive ) {
												valid = true;
												_tooltip = '';
											} else {
												_class = 'only-checkout';
												_tooltip = response.custom_labels ? labels[ 'only-checkout' ] : __( 'Only checkout', 'jet-booking' );
											}
										}
									}
								}

								// If is single night booking - exclude next day for checkout only days.
								if ( checkoutOnly && window.jetBookingState.isActive && 0 <= excludedNext.indexOf( formatted ) ) {
									valid = false;
									_tooltip = response.custom_labels ? labels.booked : __( 'Sold out', 'jet-booking' );
								}

								return window.JetPlugins.hooks.applyFilters( 'jet-booking.date-range-picker.date-show-params', [ valid, _class, _tooltip ], t );
							},
							selectForward: true,
							monthSelect: monthSelect,
							yearSelect: yearSelect
						};

						if ( startDayOffset.length && +startDayOffset ) {
							config.startDate = moment().add( +startDayOffset, 'd' );
						}

						if ( rangeEndDate ) {
							config.endDate = moment( +rangeEndDate, 'X' ).format('YYYY-MM-DD');
						}

						if ( response.custom_labels ) {
							jQuery.dateRangePickerLanguages[ 'custom' ] = labels;
							config.language = 'custom';
						}

						if ( response.weekly_bookings && ! disabledDays.length ) {
							config.batchMode = 'week';
							config.showShortcuts = false;

							if ( response.week_offset ) {
								config.weekOffset = Number( response.week_offset );
							}
						} else if ( response.one_day_bookings ) {
							config.singleDate = true;
						}

						store.commit( 'setValue', {
							key: 'dateRangePickerConfig',
							value: window.JetPlugins.hooks.applyFilters( 'jet-booking.input.config', config )
						} );

						store.commit( 'setValue', {
							key: 'isDisabled',
							value: false
						} );

						store.commit( 'setValue', {
							key: 'itemUnits',
							value: response.units.length ? response.units.map( unit => ({
								value: unit.unit_id,
								label: unit.unit_title
							}) ) : []
						} );
					}
				} ).catch( function( e ) {
					eventHub.$CXNotice.add( {
						message: e.message,
						type: 'error',
						duration: 7000,
					} );
				} );

			}
		}
	} );

	Vue.component( 'jet-abaf-bookings-list', {
		template: '#jet-abaf-bookings-list',
		mixins: [ statusMixin, itemsMethods ],
		data: function () {
			return {
				currentSort: 'booking_id'
			};
		},
		computed: {
			...Vuex.mapState( {
				pageUrl: 'pageUrl',
				sortBy: 'sortBy',
				itemsList: 'itemsList',
				perPage: 'perPage',
				offset: 'offset',
				pageNumber: 'pageNumber',
				totalItems: 'totalItems',
				statuses: state => state.all_statuses
			} )
		},
		watch: {
			itemsList( value ) {
				if ( this.pageUrl.searchParams.has( 'booking-details' ) ) {
					const bookingItem = value.find( item => item.booking_id === this.pageUrl.searchParams.get( 'booking-details' ) ) || false;

					if ( bookingItem ) {
						eventHub.$emit( 'call-popup', {
							item: bookingItem,
							state: 'info',
						} );

						this.pageUrl.searchParams.delete( 'booking-details' );
						window.history.pushState(null, '', this.pageUrl.toString());
					}
				}
			}
		},
		methods: {
			sortColumn: function ( column ) {
				this.currentSort = column;

				store.commit( 'setValue', {
					key: 'sortBy',
					value: {
						orderby: column,
						order: "DESC" === this.sortBy.order ? "ASC" : "DESC"
					}
				} );

				store.dispatch( 'getItems' );
			},
			classColumn: function ( column ) {
				return {
					'jet-abaf-active-column': column === this.currentSort,
					'jet-abaf-active-column-asc': column === this.currentSort && "DESC" === this.sortBy.order,
					'jet-abaf-active-column-desc': column === this.currentSort && "ASC" === this.sortBy.order
				};
			},
			changePage: function ( page ) {
				store.commit( 'setValue', {
					key: 'offset',
					value: this.perPage * ( page - 1 )
				} );

				store.commit( 'setValue', {
					key: 'pageNumber',
					value: page
				} );

				store.dispatch( 'getItems' );
			},
			callPopup: function ( state = false, item = false ) {
				eventHub.$emit( 'call-popup', {
					item: item,
					state: state
				} );
			}
		},
	} );

	Vue.component( 'jet-abaf-bookings-filter', {
		template: '#jet-abaf-bookings-filter',
		mixins: [ fieldsManager ],
		components: {
			vuejsDatepicker: window.vuejsDatepicker,
		},
		data () {
			return {
				currentMode: 'all',
				expandFilters: false,
				dateFormat: 'dd/MM/yyyy',
				showExportPopup: false,
				exportType: 'all',
				exportFormat: 'csv',
				exportDataReturnType: 'id',
				exportDateFormat: 'Y-m-d',
			}
		},
		computed: {
			...Vuex.mapState( [ 'filters', 'currentFilters', 'currentView', 'monday_first', 'export_nonce', 'export_url' ] ),
		},
		created: function () {
			this.currentMode = getCurrentMode();
		},
		methods: {
			setMode ( mode ) {
				window.location.hash = '#' + mode;
				this.currentMode = mode;

				store.commit( 'setValue', {
					key: 'offset',
					value: 0
				} );

				store.commit( 'setValue', {
					key: 'pageNumber',
					value: 1
				} );

				store.dispatch( 'getItems' );
			},
			modeButtonStyle ( mode ) {
				return this.currentMode === mode ? 'accent' : 'link-accent';
			},
			updateFilters: function ( value, name, type ) {
				let filterValue = value.target ? value.target.value : value;
				let currentFilter = {};

				if ( 'date-picker' === type ) {
					filterValue = value ? moment( filterValue ).format( 'MMMM DD YYYY' ) : '';
				}

				if ( filterValue.length ) {
					currentFilter = { [ name ]: filterValue };
				} else {
					delete this.currentFilters[ name ];
				}

				store.commit( 'setValue', {
					key: 'currentFilters',
					value: Object.assign( {}, this.currentFilters, currentFilter )
				} );

				store.commit( 'setValue', {
					key: 'offset',
					value: 0
				} );

				store.commit( 'setValue', {
					key: 'pageNumber',
					value: 1
				} );

				store.dispatch( 'getItems' );
			},
			clearFilter: function () {
				store.commit( 'setValue', {
					key: 'currentFilters',
					value: {}
				} );

				store.commit( 'setValue', {
					key: 'offset',
					value: 0
				} );

				store.commit( 'setValue', {
					key: 'pageNumber',
					value: 1
				} );

				store.dispatch( 'getItems' );
			},
			isVisible ( id, filter, type ) {
				if ( type !== filter.type ) {
					return false;
				}

				if ( 'select' === filter.type && ! Object.keys( filter.value ).length ) {
					return false;
				}

				if ( 'date-picker' === filter.type && 'list' !== this.currentView ) {
					return false;
				}

				return true;
			},
			prepareObjectForOptions: function ( input ) {
				let result = [ {
					'value': '',
					'label': __( 'Select...', 'jet-booking' ),
				} ];

				for ( const value in input ) {
					if ( input.hasOwnProperty( value ) ) {
						result.push( {
							'value': value,
							'label': input[ value ],
						} );
					}
				}

				return result;
			},
			doExport () {
				let urlParts = {
					type: this.exportType,
					format: this.exportFormat,
					return: this.exportDataReturnType,
					date_format: this.exportDateFormat,
					nonce: this.export_nonce,
				};

				if ( 'filtered' === this.exportType ) {
					urlParts = {
						...urlParts,
						...{
							filters: JSON.stringify( store.state.currentFilters ),
							sort: JSON.stringify( store.state.sortBy ),
							per_page: 0,
							mode: getCurrentMode(),
						}
					};
				}

				window.location = this.export_url + '&' + buildQuery( urlParts );
			},
		}
	} );

	Vue.component( 'jet-abaf-bookings-view', {
		template: '#jet-abaf-bookings-view',
		computed: { ...Vuex.mapState( [ 'pageUrl', 'currentFilters', 'currentView', 'views' ] ) },
		methods: {
			viewButtonStyle ( view ) {
				return this.currentView === view ? 'accent' : 'link-accent';
			},
			updateView: function ( view ) {
				store.commit( 'setValue', {
					key: 'currentView',
					value: view
				} );

				this.pageUrl.searchParams.set( 'view', view );

				if ( 'all' !== getCurrentMode() ) {
					this.pageUrl.hash = getCurrentMode();
				}

				window.history.pushState( null, '', this.pageUrl.toString() );

				const newFilters = Object.assign( {}, this.currentFilters, { 'check_in_date': '', 'check_out_date': '', 'date': '' } );

				store.commit( 'setValue', {
					key: 'currentFilters',
					value: newFilters
				} );

				store.dispatch( 'getItems' );
			}
		},
	} );

	Vue.component('jet-abaf-bookings-calendar', {
		template: '#jet-abaf-bookings-calendar',
		mixins: [ dateMethods, statusMixin, itemsMethods ],
		data() {
			return {
				masks: { weekdays: 'WWW' },
				maxItemInCell: 3
			}
		},
		components: {
			vCalendar: window.vCalendar,
		},
		computed: Vuex.mapState( {
			currentFilters: state => state.currentFilters,
			dayIndex: state => state.monday_first ? 2 : 1,
			itemsList: function ( state ) {
				const self = this;

				return state.itemsList.map( function ( item ) {
					return {
						key: item.booking_id,
						customData: { ...item },
						dates: self.createRange( item.check_in_date_timestamp, item.check_out_date_timestamp )
					}
				} );
			},
			pageUrl: 'pageUrl'
		} ),
		methods: {
			callPopup: function ( state = false, item = false ) {
				eventHub.$emit( 'call-popup', {
					item: item,
					state: state
				} );
			},
			createRange: function ( start, end, step = 86400 ) {
				const range = [ this.timestampToDate( start, "MMM DD YYYY" ) ];

				if ( this.timestampToDate( start, "MMM DD YYYY" ) === this.timestampToDate( end, "MMM DD YYYY" ) ) {
					return range;
				}

				let newItem = +start;

				while ( newItem < +end ) {
					range.push( this.timestampToDate( newItem += step, "MMM DD YYYY" ) );
				}

				return range;
			},
			getRemainingItemCount: function ( attributes ) {
				return attributes && attributes.length > this.maxItemInCell ? attributes.length - this.maxItemInCell : 0;
			},
			showMore: function ( day ) {
				const date = this.objectTimeToTimestamp( new Date( day.year, day.month -1, day.day ) );
				const newFilters = Object.assign( {}, this.currentFilters, { 'date': date } );

				store.commit( 'setValue', {
					key: 'currentFilters',
					value: newFilters
				} );

				store.commit( 'setValue', {
					key: 'currentView',
					value: 'list'
				} );

				this.pageUrl.searchParams.set( 'view', 'list' );
				window.history.pushState( null, '', this.pageUrl.toString() );

				store.dispatch( 'getItems' );
			},
			mouseEnter: function ( event ) {
				jQuery( '.jet-abaf-calendar-day-booking' ).each( function() {
					if ( jQuery( event.target ).data( 'booking-id' ) === jQuery( this ).data( 'booking-id' ) ) {
						jQuery( this ).find( '.jet-abaf-booking-data' ).addClass( 'active' );
					}
				} );
			},
			mouseLeave: function ( event ) {
				jQuery( '.jet-abaf-calendar-day-booking' ).each( function() {
					if ( jQuery( event.target ).data( 'booking-id' ) === jQuery( this ).data( 'booking-id' ) ) {
						jQuery( this ).find( '.jet-abaf-booking-data' ).removeClass( 'active' );
					}
				} );
			},
		},
	});

	Vue.component('jet-abaf-bookings-timeline', {
		template: '#jet-abaf-bookings-timeline',
		mixins: [ itemsMethods, statusMixin ],
		components: {
			vuejsDatepicker: window.vuejsDatepicker,
		},
		data() {
			return {
				dateFormat: 'MMMM yyyy',
				selectedDate: moment().format("MMMM YYYY")
			}
		},
		computed: {
			startTime: function () {
				return moment( this.selectedDate, 'MMMM YYYY' ).startOf( 'month' ).format( 'YYYY-MM-DD' );
			},
			endTime: function () {
				return moment( this.selectedDate, 'MMMM YYYY' ).endOf( 'month' ).format( 'YYYY-MM-DD' );
			},
			...Vuex.mapState( {
				itemsList: function ( state ) {
					const self = this;
					let itemsList = [];

					state.itemsList.map( function ( item ) {
						let apartmentID = +item.apartment_id;

						if ( ! itemsList[ apartmentID ] ) {
							itemsList[ apartmentID ] = {
								id: apartmentID,
								instance: self.getItemLabel( apartmentID ),
								gtArray: []
							}
						}

						itemsList[ apartmentID ].gtArray.push( {
							id: +item.booking_id,
							start: moment( +item.check_in_date_timestamp, 'X' ).startOf( 'day' ).format( 'YYYY-MM-DD HH:mm:ss' ),
							end: moment( +item.check_out_date_timestamp, 'X' ).endOf( 'day' ).format( 'YYYY-MM-DD HH:mm:ss' ),
							customData:{ ...item }
						} );
					} );

					itemsList = itemsList.filter( item => item );

					return itemsList;
				}
			} )
		},
		watch: {
			selectedDate() {
				this.adjustHeight();
				this.$refs.gantt.scrollToPostionHandle( { x:0, y:0 } )
			}
		},
		updated: function () {
			this.adjustHeight();
		},
		methods: {
			adjustHeight: function () {
				const leftBarItems = jQuery( '.gantt-leftbar-item:not( .gantt-block-top-space )' );

				jQuery( '.gantt-block:not(.gantt-block-top-space)' ).each( function( index ) {
					const ganttBlock = jQuery( this );

					setTimeout( function() {
						leftBarItems[ index ].style.setProperty( 'height', ganttBlock.outerHeight() - 1 + 'px', 'important' );
					}, 0 );
				} );
			},
			callPopup: function ( state = false, item = false ) {
				eventHub.$emit( 'call-popup', {
					item: item,
					state: state
				} );
			}
		},
	});

	Vue.component( 'jet-abaf-add-new-booking', {
		template: '#jet-abaf-add-new-booking',
		mixins: [ fieldsManager ],
		data: function () {
			return {
				addDialog: false,
				newItem: {
					status: '',
					apartment_id: '',
					check_in_date: '',
					check_out_date: '',
				},
				datePickerFormat: 'dd-MM-yyyy',
				dateMomentFormat: 'DD-MM-YYYY',
				createRelatedOrder: false,
				bookingOrderStatus: 'draft',
				wcOrderFirstName: '',
				wcOrderLastName: '',
				wcOrderEmail: '',
				wcOrderPhone: '',
				submitting: false
			}
		},
		computed: {
			...Vuex.mapState( {
				bookingMode: state => state.booking_mode,
				statuses: state => state.all_statuses,
				bookingInstances: state => state.bookings,
				orderPostType: state => state.order_post_type,
				orderPostTypeStatuses: state => state.order_post_type_statuses,
				wcIntegration: state => state.wc_integration,
				overlappingBookings: 'overlappingBookings',
				fields: function ( state ) {
					return [ ...state.columns, ...state.additional_columns ];
				}
			} ),
			computedNewItem: function () {
				return Object.assign( {}, this.newItem );
			}
		},
		watch: {
			computedNewItem: {
				handler: function ( value, oldValue ) {
					if ( ! Object.keys( value ).length || ! Object.keys( oldValue ).length ) {
						return;
					}

					if ( ! value.apartment_id.length || ! value?.check_in_date?.length || ! value?.check_out_date?.length ) {
						return;
					}

					if (
						value.apartment_id !== oldValue.apartment_id
						|| value.check_in_date && ! moment( value.check_in_date ).isSame( oldValue.check_in_date, 'day' )
						|| value.check_out_date && ! moment( value.check_out_date ).isSame( oldValue.check_out_date, 'day' )
					) {
						this.getBookingPrice( value );
					}
				},
				deep: true,
			},
		},
		methods: {
			showAddDialog: function () {
				this.addDialog = true;

				store.commit( 'setValue', {
					key: 'overlappingBookings',
					value: false
				} );

				store.commit( 'setValue', {
					key: 'isDisabled',
					value: true
				} );

				store.commit( 'setValue', {
					key: 'bookingPrice',
					value: 0
				} );

				store.commit( 'setValue', {
					key: 'bookingItem',
					value: this.newItem
				} );

				if ( this.newItem.apartment_id.length ) {
					this.initDateRangePicker();
					this.getBookingPrice( this.newItem );
				}
			},

			checkRequiredFields: function () {
				let requiredFields = [ 'status', 'apartment_id', 'check_in_date', 'check_out_date' ],
					emptyFields = [],
					invalidFields = [],
					message = '';

				for ( let field of requiredFields ) {
					if ( ! this.newItem[ field ].length ) {
						switch ( field ) {
							case 'status':
								emptyFields.push( 'Status' );
								break;
							case 'apartment_id':
								emptyFields.push( 'Booking item' );
								break;
							case 'check_in_date':
								emptyFields.push( 'Check in/out' );
								break;
						}
					}
				}

				if ( (this.wcIntegration && this.createRelatedOrder) || 'wc_based' === this.bookingMode ) {
					if ( ! this.wcOrderFirstName.length ) {
						emptyFields.push( 'First name' );
					}

					if ( ! this.wcOrderLastName.length ) {
						emptyFields.push( 'Last name' );
					}

					if ( ! this.wcOrderEmail.length ) {
						emptyFields.push( 'Email' );
					} else {
						if ( ! this.wcOrderEmail.match( /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ ) ) {
							invalidFields.push( 'Email' );
						}
					}
				}

				if ( ! emptyFields.length && ! invalidFields.length ) {
					return true;
				} else if ( emptyFields.length ) {
					emptyFields = emptyFields.join( ', ' ).toLowerCase();
					message = sprintf( __( 'Empty fields: %s.', 'jet-booking' ), emptyFields );
				} else if ( invalidFields.length ) {
					invalidFields = invalidFields.join( ', ' ).toLowerCase();
					message = sprintf( __( 'Invalid value fields: %s.', 'jet-booking' ), invalidFields );
				}

				eventHub.$CXNotice.add( {
					message: message,
					type: 'error',
					duration: 7000,
				} );

				return false;
			},

			handleAdd: function () {
				let self = this;

				self.addDialog = true;

				if ( ! self.checkRequiredFields() ) {
					return;
				}

				store.commit( 'setValue', {
					key: 'overlappingBookings',
					value: false
				} );

				const data = {
					item: self.newItem
				}

				if ( (self.createRelatedOrder && self.wcIntegration) || 'wc_based' === this.bookingMode ) {
					data.relatedOrder = {
						firstName: self.wcOrderFirstName,
						lastName: self.wcOrderLastName,
						email: self.wcOrderEmail,
						phone: self.wcOrderPhone,
					}
				} else if ( self.createRelatedOrder && self.orderPostType ) {
					data.relatedOrder = {
						orderStatus: self.bookingOrderStatus
					};
				}

				self.submitting = true;

				wp.apiFetch( {
					method: 'post',
					path: window.JetABAFConfig.api.add_booking,
					data: data
				} ).then( function ( response ) {
					if ( ! response.success ) {
						if ( response.overlapping_bookings ) {
							eventHub.$CXNotice.add( {
								message: response.data,
								type: 'error',
								duration: 7000,
							} );

							store.commit( 'setValue', {
								key: 'overlappingBookings',
								value: response.html
							} );

							self.initDateRangePicker();
							self.submitting = false;

							return;
						} else {
							eventHub.$CXNotice.add( {
								message: response.data,
								type: 'error',
								duration: 7000,
							} );
						}
					} else {
						self.addDialog = false;

						eventHub.$CXNotice.add( {
							message: 'Done!',
							type: 'success',
							duration: 7000,
						} );

						store.dispatch( 'getItems' );
					}

					self.newItem = { status: '', apartment_id: '', check_in_date: '', check_out_date: '' };
					self.createRelatedOrder = false;
					self.bookingOrderStatus = 'draft';
					self.wcOrderFirstName = '';
					self.wcOrderLastName = '';
					self.wcOrderEmail = '';
					self.wcOrderPhone = '';
					self.submitting = false;
				} ).catch( function ( e ) {
					eventHub.$CXNotice.add( {
						message: e.message,
						type: 'error',
						duration: 7000,
					} );
				} );
			}
		}
	} );

	Vue.component( 'jet-abaf-popup', {
		template: '#jet-abaf-popup',
		mixins: [ fieldsManager, itemsMethods, statusMixin ],
		data: function () {
			return {
				calculateTotals: false,
				currentItem: false,
				editDialog: false,
				isShow: false,
				popUpState: '',
				recalculateTotals: false,
				submitting: false
			};
		},
		computed: {
			...Vuex.mapState( {
				overlappingBookings: 'overlappingBookings',
				bookingInstances: state => state.bookings,
				bookingMode: state => state.booking_mode,
				statuses: state => state.all_statuses
			} ),
			computedCurrentItem: function () {
				return Object.assign( {}, this.currentItem );
			}
		},
		watch: {
			computedCurrentItem: {
				handler: function ( value, oldValue ) {
					if ( ! Object.keys( value ).length || ! Object.keys( oldValue ).length ) {
						return;
					}

					if (
						value.apartment_id !== oldValue.apartment_id
						|| value.check_in_date && ! moment( value.check_in_date ).isSame( +oldValue.check_in_date, 'day' )
						|| value.check_out_date && ! moment( value.check_out_date ).isSame( +oldValue.check_out_date, 'day' )
					) {
						if ( 'wc_based' === this.bookingMode ) {
							this.recalculateTotals = true;
						}

						this.getBookingPrice( value );
					}
				},
				deep: true,
			},
			editDialog ( value ) {
				if ( ! value ) {
					this.currentItem = false;
					this.recalculateTotals = false;
					this.calculateTotals = false;
				}
			}
		},
		mounted: function () {
			eventHub.$on( 'call-popup', this.callPopup );
			eventHub.$on( 'cancel-popup', this.cancelPopup );
		},
		methods: {
			callPopup: function ( { state, item } ) {
				this.isShow = true;
				this.popUpState = state;
				this.currentItem = item;

				if ( 'info' === state ) {
					this.getBookingPrice( item );
				} else if ( 'update' === state ) {
					this.openUpdatePopup( item );
				}
			},
			cancelPopup: function () {
				this.isShow = false ;
				this.popUpState = '';
				this.currentItem = false;
			},
			updateDetailsItem: function ( item ) {
				this.popUpState = 'update';
				this.openUpdatePopup( item );
			},
			openUpdatePopup: function ( item ) {
				this.editDialog = true;

				store.commit( 'setValue', {
					key: 'overlappingBookings',
					value: false
				} );

				this.currentItem = JSON.parse( JSON.stringify( item ) );
				this.currentItem.check_in_date = moment.unix( this.currentItem.check_in_date_timestamp ).utc().format( 'YYYY-MM-DD' );
				this.currentItem.check_out_date = moment.unix( this.currentItem.check_out_date_timestamp ).utc().format( 'YYYY-MM-DD' );

				store.commit( 'setValue', {
					key: 'bookingPrice',
					value: 0
				} );

				store.commit( 'setValue', {
					key: 'bookingItem',
					value: this.currentItem
				} );

				this.initDateRangePicker();
				this.getBookingPrice( this.currentItem );
			},
			updateItem: function () {
				let self = this;

				self.editDialog = true;

				if ( ! self.currentItem ) {
					return;
				}

				store.commit( 'setValue', {
					key: 'overlappingBookings',
					value: false
				} );

				if ( ! self.itemUnits.length ) {
					self.currentItem.apartment_unit = null;
				}

				const data = {
					item: self.currentItem
				}

				if ( 'wc_based' === self.bookingMode ) {
					data.calculateTotals = self.calculateTotals;
				}

				self.submitting = true;

				wp.apiFetch( {
					method: 'post',
					path: window.JetABAFConfig.api.update_booking + self.currentItem.booking_id + '/',
					data: data
				} ).then( function ( response ) {
					if ( ! response.success ) {
						if ( response.overlapping_bookings ) {
							self.$CXNotice.add( {
								message: response.data,
								type: 'error',
								duration: 7000,
							} );

							store.commit( 'setValue', {
								key: 'overlappingBookings',
								value: response.html
							} );

							self.initDateRangePicker();
							self.submitting = false;

							return;
						} else {
							self.$CXNotice.add( {
								message: response.data,
								type: 'error',
								duration: 7000,
							} );
						}
					} else {
						self.editDialog = false;

						self.$CXNotice.add( {
							message: 'Done!',
							type: 'success',
							duration: 7000,
						} );

						store.dispatch( 'getItems' );
					}

					self.recalculateTotals = false;
					self.calculateTotals = false;
					self.submitting = false;

					self.cancelPopup();
				} ).catch( function ( e ) {
					self.$CXNotice.add( {
						message: e.message,
						type: 'error',
						duration: 7000,
					} );

					self.recalculateTotals = false;
					self.calculateTotals = false;
					self.submitting = false;

					self.cancelPopup();
				} );
			},
			deleteDetailsItem: function () {
				this.popUpState = 'delete';
			},
			deleteItem: function () {
				const self = this;

				if ( ! self.currentItem ) {
					return;
				}

				self.submitting = true;

				wp.apiFetch( {
					method: 'delete',
					path: window.JetABAFConfig.api.delete_booking + self.currentItem.booking_id + '/',
				} ).then( function ( response ) {
					if ( ! response.success ) {
						self.$CXNotice.add( {
							message: response.data,
							type: 'error',
							duration: 7000,
						} );
					}

					store.commit( 'setValue', {
						key: 'offset',
						value: 0
					} );

					store.commit( 'setValue', {
						key: 'pageNumber',
						value: 1
					} );

					store.dispatch( 'getItems' );

					self.submitting = false;

					self.cancelPopup();
				} ).catch( function ( e ) {
					self.$CXNotice.add( {
						message: e.message,
						type: 'error',
						duration: 7000,
					} );

					self.cancelPopup();
				} );
			},
		},
	} );

	new Vue( {
		el: '#jet-abaf-bookings-page',
		template: '#jet-abaf-bookings',
		store,
		computed: Vuex.mapState( {
			isSet: state => state.setup.is_set,
			bookingsList: state => state.bookings_list,
			currentView: state => `jet-abaf-bookings-${ state.currentView }`,
			isLoading: 'isLoading',
			pageUrl: 'pageUrl',
			perPage: 'perPage',
		} ),
		created: function () {
			if ( this.pageUrl.searchParams.has( 'booking-details' ) ) {
				const index = this.bookingsList.reverse().findIndex( item => item.booking_id === this.pageUrl.searchParams.get( 'booking-details' ) );
				const page = Math.ceil( ( index + 1 ) / this.perPage ) || 1;

				store.commit( 'setValue', {
					key: 'offset',
					value: this.perPage * ( page - 1 )
				} );

				store.commit( 'setValue', {
					key: 'pageNumber',
					value: page
				} );
			}

			if ( this.pageUrl.searchParams.has( 'view' ) ) {
				const view = [ 'list', 'calendar', 'timeline' ].includes( this.pageUrl.searchParams.get( 'view' ) ) ? this.pageUrl.searchParams.get( 'view' ) : 'list';

				store.commit( 'setValue', {
					key: 'currentView',
					value: view
				} );
			}

			store.dispatch( 'getItems' );
		},
	} );

})();