/* global wcboost_wishlist_params */
( function( $ ) {
	/**
	 * Check if a node is blocked for processing.
	 *
	 * @param {JQuery Object} $node
	 * @return {bool} True if the DOM Element is UI Blocked, false if not.
	 */
	var is_blocked = function( $node ) {
		return $node.is( '.processing' ) || $node.parents( '.processing' ).length;
	};

	/**
	 * Block a node visually for processing.
	 *
	 * @param {JQuery Object} $node
	 */
	var block = function( $node ) {
		if ( ! $.fn.block || ! $node ) {
			return;
		}

		if ( ! is_blocked( $node ) ) {
			$node.addClass( 'processing' ).block( {
				message: null,
				overlayCSS: {
					background: '#fff',
					opacity: 0.6
				}
			} );
		}
	};

	/**
	 * Unblock a node after processing is complete.
	 *
	 * @param {JQuery Object} $node
	 */
	var unblock = function( $node ) {
		if ( ! $.fn.unblock || ! $node ) {
			return;
		}

		$node.removeClass( 'processing' ).unblock();
	};

	/**
	 * Flyout notices
	 *
	 * @param {string} message
	 * @param {object} options
	 */
	var WCBoostNotice = function( message, options ) {
		this.options = $.extend( {
			duration: 3000,
			type: 'notice',
		}, options );

		this.$notice = null;
		this.$wrapper = $( '#wcboost-flyout-notices-container' );

		if ( ! this.$wrapper.length ) {
			this.$wrapper = $( '<div id="wcboost-flyout-notices-container" class="wcboost-flyout-notices-container" />' ).appendTo( document.body );
		}

		this.$notice = $( '<div class="wcboost-flyout-notice wcboost-notice" role="alert"/>' )
			.addClass( 'wcboost-notice--' + this.options.type )
			.append( $( message ) );

		this.wait = null;

		// Methods.
		this.show = this.show.bind( this );
		this.hide = this.hide.bind( this );
		this.delayHide = this.delayHide.bind( this );
		this.resetDelayHide = this.resetDelayHide.bind( this );

		// Events.
		if ( this.options.duration > 0 ) {
			this.$notice
				.on( 'mouseenter', this.resetDelayHide )
				.on( 'mouseleave', this.delayHide );
		}
	}

	WCBoostNotice.prototype.show = function() {
		if ( ! this.$notice ) {
			return;
		}

		this.$notice.hide();
		this.$wrapper.append( this.$notice );
		this.$notice.fadeIn();

		if ( this.options.duration > 0 ) {
			this.delayHide();
		}
	}

	WCBoostNotice.prototype.delayHide = function() {
		this.resetDelayHide();
		this.wait = setTimeout( this.hide, this.options.duration );
	}

	WCBoostNotice.prototype.hide = function() {
		this.$notice.fadeOut();
	}

	WCBoostNotice.prototype.resetDelayHide = function() {
		clearTimeout( this.wait );
	}

	/**
	 * AddToWishlistHandler class
	 */
	var AddToWishlistHandler = function() {
		this.selectors = {
			text: '.wcboost-wishlist-button__text',
			icon: '.wcboost-wishlist-button__icon',
		};

		this.addToWishlist      = this.addToWishlist.bind( this );
		this.removeFromWishlist = this.removeFromWishlist.bind( this );
		this.updateButton       = this.updateButton.bind( this );

		// Events.
		$( document.body ).on( 'click', '.wcboost-wishlist-button--ajax', { addToWishlistHandler: this }, this.onButtonClick );

		if ( 'yes' === wcboost_wishlist_params.allow_adding_variations ) {
			$( '.variations_form' )
				.on( 'found_variation', { addToWishlistHandler: this }, this.onVariationFound )
				.on( 'reset_data', { addToWishlistHandler: this }, this.onVariationReset );
		}
	}

	AddToWishlistHandler.prototype.onButtonClick = function( event ) {
		var self = event.data.addToWishlistHandler;
		var $button = $( event.currentTarget );

		if ( ! $button.hasClass( 'added' ) ) {
			event.preventDefault();
			self.addToWishlist( $button );
		} else if ( 'remove' === wcboost_wishlist_params.exists_item_behavior ) {
			event.preventDefault();
			self.removeFromWishlist( $button );
		}
	}

	AddToWishlistHandler.prototype.addToWishlist = function( $button ) {
		var self = this;
		var data = {
			product_id: $button.data( 'product_id' ),
			quantity: $button.data( 'quantity' ),
		};

		if ( ! data.product_id ) {
			return;
		}

		$.post( {
			url: woocommerce_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'add_to_wishlist' ),
			data: data,
			dataType: 'json',
			beforeSend: function() {
				$button.removeClass( 'added' ).addClass( 'loading' );
				self.updateButton( $button, 'loading' );
			},
			success: function( response ) {
				if ( ! response.success ) {
					if ( response.data && response.data.message ) {
						var notice = new WCBoostNotice( response.data.message );
						notice.show();
					}

					if ( response.data && response.data.redirect_url ) {
						location.href = response.data.redirect_url;
					}

					self.updateButton( $button, 'removed' );
					return;
				}

				var fragments = response.data.fragments;

				self.updateButton( $button, 'added', response.data );

				// if ( $button.data( 'variations' ) ) {
				// 	self.updateButton( $button, 'update_variations', { variation_id: response.data.product_id, added: 'yes' } );
				// }

				$( document.body )
					.trigger( 'added_to_wishlist', [ $button, fragments ] )
					.trigger( 'wishlist_item_added', [ response.data ] );

				if ( 'yes' === wcboost_wishlist_params.wishlist_redirect_after_add ) {
					window.location = wcboost_wishlist_params.wishlist_url;
				}
			},
			complete: function() {
				$button.removeClass( 'loading' );
			}
		} );
	}

	AddToWishlistHandler.prototype.removeFromWishlist = function( $button ) {
		var self = this;
		var params = new URLSearchParams( $button[0].search );
		var data = {
			item_key: params.get( 'remove-wishlist-item' ),
			_wpnonce: params.get( '_wpnonce' ),
		};

		if ( ! data.item_key ) {
			return;
		}

		$.post( {
			url: woocommerce_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'remove_wishlist_item' ),
			data: data,
			dataType: 'json',
			beforeSend: function() {
				$button.removeClass( 'added' ).addClass( 'loading' );
				self.updateButton( $button, 'loading' );
			},
			success: function( response ) {
				if ( ! response.success ) {
					return;
				}

				var fragments = response.data.fragments;

				self.updateButton( $button, 'removed', response.data );

				// if ( $button.data( 'variations' ) ) {
				// 	self.updateButton( $button, 'update_variations', { variation_id: response.data.product_id, added: 'no' } );
				// }

				$( document.body )
					.trigger( 'removed_from_wishlist', [ $button, fragments ] )
					.trigger( 'wishlist_item_removed', [ response.data ] );
			},
			complete: function() {
				$button.removeClass( 'loading' );
			}
		} );
	}

	AddToWishlistHandler.prototype.onVariationFound = function( event, data ) {
		var self       = event.data.addToWishlistHandler;
		var $button    = $( event.target ).closest( '.product' ).find( '.wcboost-wishlist-button' );
		var variations = $button.data( 'variations' );

		self.updateButton( $button, 'update_id', { product_id: data.variation_id } );

		if ( 'yes' === wcboost_wishlist_params.allow_adding_variations && variations ) {
			var found = variations.find( function( variation ) {
				return variation.variation_id === data.variation_id;
			} );

			if ( found ) {
				self.updateButton( $button, found.added === 'yes' ? 'added' : 'removed', found );
			}
		}
	}

	AddToWishlistHandler.prototype.onVariationReset = function( event ) {
		var self       = event.data.addToWishlistHandler;
		var $button    = $( event.target ).closest( '.product' ).find( '.wcboost-wishlist-button' );
		var variations = $button.data( 'variations' );
		var product_id = null;

		self.updateButton( $button, 'update_id', { product_id: null } );

		if ( variations ) {
			var parent = variations.find( function( variation ) {
				return variation.is_parent;
			} );

			if ( parent ) {
				product_id = parent.variation_id;
			}

			if ( 'yes' === wcboost_wishlist_params.allow_adding_variations && parent ) {
				self.updateButton( $button, parent.added === 'yes' ? 'added' : 'removed', parent );
			}
		}

		if ( ! product_id ) {
			var params = new URLSearchParams( $button[0].search );
			product_id = params.get( 'add-to-wishlist' );
		}

		self.updateButton( $button, 'update_id', { product_id: product_id } );
	}

	AddToWishlistHandler.prototype.updateButton = function( $button, status, data ) {
		switch ( status ) {
			case 'loading':
				$button.addClass( 'loading' );
				$button.find( this.selectors.icon ).html( wcboost_wishlist_params.icon_loading );
				break;

			case 'added':
				$button.removeClass( 'loading' ).addClass( 'added' );

				switch ( wcboost_wishlist_params.exists_item_behavior ) {
					case 'view_wishlist':
						$button.attr( 'href', data.wishlist_url ? data.wishlist_url : wcboost_wishlist_params.wishlist_url );
						$button.find( this.selectors.text ).text( wcboost_wishlist_params.i18n_view_wishlist );
						$button.find( this.selectors.icon ).html( wcboost_wishlist_params.icon_filled );
						break;

					case 'remove':
						$button.attr( 'href', data.remove_url );
						$button.find( this.selectors.text ).text( wcboost_wishlist_params.i18n_remove_from_wishlist );
						$button.find( this.selectors.icon ).html( wcboost_wishlist_params.icon_filled );
						break;

					case 'hide':
						$button.hide();
						break;
				}

				break;

			case 'removed':
				$button.removeClass( 'added loading' );
				$button.find( this.selectors.text ).text( wcboost_wishlist_params.i18n_add_to_wishlist );
				$button.find( this.selectors.icon ).html( wcboost_wishlist_params.icon_normal );

				if ( data && data.add_url ) {
					$button.attr( 'href', data.add_url );
				}
				break;

			case 'update_id':
				$button.data( 'product_id', data.product_id ).attr( 'data-product_id', data.product_id );
				break;

			// case 'update_variations':
			// 	var variations = $button.data( 'variations' );

			// 	if ( variations && data.variation_id ) {
			// 		var index = variations.findIndex( function( variation ) { return variation.variation_id === data.variation_id; } );

			// 		variations[ index ] = $.extend( {}, variations[ index ], data );

			// 		$button.data( 'variations', variations );
			// 	}
			// 	break;
		}
	}

	/**
	 * WCBoostWishlist class
	 */
	var WCBoostWishlist = function( $form ) {
		var self = this;

		self.$form = $form;
		self.$wrapper = $form.closest( '.wcboost-wishlist' );

		self.updateForm = self.updateForm.bind( self );
		self.showNotices = self.showNotices.bind( self );

		// Initial states.
		self.$wrapper.off( '.wcboost-wishlist' );

		// Events.
		self.$wrapper.on( 'click.wcboost-wishlist', '.wcboost-wishlist-form .product-remove > a', { wishlist: self }, self.onRemoveItem );
		self.$wrapper.on( 'click.wcboost-wishlist', 'a.restore-item', { wishlist: self }, self.onRestoreItem );
		self.$wrapper.on( 'change.wcboost-wishlist input.wcboost-wishlist', ':input', { wishlist: self }, self.onInputChagne );
		self.$wrapper.on( 'submit.wcboost-wishlist', 'form',  { wishlist: self }, self.onSubmitForm );

		self.$form.find( 'button[name="update_wishlist"]' ).prop( 'disabled', true ).attr( 'aria-disabled', true );
	}

	WCBoostWishlist.prototype.onRemoveItem = function( event ) {
		event.preventDefault();

		var self = event.data.wishlist;

		$.ajax( {
			url:       event.currentTarget.href,
			type:     'GET',
			dataType: 'html',
			beforeSend: function() {
				block( self.$form );
			},
			success:  function( response ) {
				self.updateForm( response );
			},
			complete: function() {
				if ( self.$form ) {
					unblock( self.$form );
				}

				// Scroll to notices.
				var $notices = $( '[role="alert"]' );

				if ( $notices.length ) {
					$( 'html, body' ).animate( {
						scrollTop: ( $notices.offset().top - 100 )
					}, 1000 );
				}
			}
		} );
	}

	WCBoostWishlist.prototype.onRestoreItem = function( event ) {
		event.preventDefault();

		var self = event.data.wishlist,
			$blocking = self.$form ? self.$form : self.$wrapper;

		$.ajax( {
			url     : event.currentTarget.href,
			type    : 'GET',
			dataType: 'html',
			beforeSend: function() {
				block( $blocking );
			},
			success:  function( response ) {
				self.updateForm( response );
			},
			complete: function() {
				unblock( $blocking );
			}
		} );
	}

	WCBoostWishlist.prototype.onInputChagne = function( event ) {
		var self = event.data.wishlist;

		self.$form.find( 'button[name="update_wishlist"]' ).prop( 'disabled', false ).attr( 'aria-disabled', false );
	}

	WCBoostWishlist.prototype.onSubmitForm = function( event ) {
		event.preventDefault();

		var self = event.data.wishlist;

		// Provide the action input because the form-handler expectes it.
		$( '<input />' )
			.attr( 'type', 'hidden' )
			.attr( 'name', 'update_wishlist' )
			.attr( 'value', 'Update Wishlist' )
			.appendTo( self.$form );

		$.ajax( {
			type: self.$form.attr( 'method' ),
			url:  self.$form.attr( 'action' ),
			data: self.$form.serialize(),
			dataType: 'html',
			beforeSend: function() {
				block( self.$form );
			},
			success: function( response ) {
				self.updateForm( response );
			},
			complete: function() {
				if ( self.$form ) {
					unblock( self.$form );
				}
			}
		} );
	}

	WCBoostWishlist.prototype.updateForm = function( html ) {
		var self = this,
			$html = $.parseHTML( html ),
			$form = $( '.wcboost-wishlist-form', $html ),
			$notices = $( '.woocommerce-error, .woocommerce-message, .woocommerce-info, .is-info, .is-success, .is-error', $html );

		// Remove current notices.
		$( '.woocommerce-error, .woocommerce-message, .woocommerce-info, .is-info, .is-success, .is-error' ).remove();

		if ( ! $form.length ) {

			var $emptyWishlist = $( '.wishlist-empty', $html ).closest( '.wcboost-wishlist' );

			// Notices are handled later.
			$emptyWishlist
				.find( '.woocommerce-error, .woocommerce-message, .woocommerce-info, .is-info, .is-success, .is-error' )
				.filter( function() {
					if ( $( this ).closest( '.wishlist-empty' ).length ) {
						return false;
					}

					return ! $( this ).hasClass( 'wishlist-empty' );
				} )
				.remove();

			self.$wrapper.html( $emptyWishlist.html() );
			self.$form = null;

			// Remove the template's notice from the list of notices.
			$notices = $notices.filter( function() {
				if ( $( this ).closest( '.wishlist-empty' ).length ) {
					return false;
				}

				return ! $( this ).hasClass( 'wishlist-empty' );
			} );

			// Notify plugins that the cart was emptied.
			$( document.body ).trigger( 'wishlist_emptied', [ self ] );
		} else {
			if ( self.$form ) {
				self.$form.replaceWith( $form );
				self.$form = $form;
			} else {
				var $wrapper = $form.closest( '.wcboost-wishlist' );

				self.$wrapper.html( $wrapper.html() );
				self.$form = self.$wrapper.find( '.wcboost-wishlist-form' );
			}

			self.$form.find( 'button[name="update_wishlist"]' ).prop( 'disabled', true ).attr( 'aria-disabled', true );
		}

		if ( $notices && $notices.length > 0 ) {
			self.showNotices( $notices );
		}

		$( document.body ).trigger( 'wishlist_updated', [ self ] );
	}

	WCBoostWishlist.prototype.showNotices = function( $notices, $target ) {
		if ( $target ) {
			$target.prepend( $notices );
		} else {
			this.$wrapper.prepend( $notices );
		}
	}

	/**
	 * WishlistShareHandler class
	 */
	var WishlistShareHandler = function() {
		var self = this;

		self.openSocialShareIframe = self.openSocialShareIframe.bind( self );
		self.showCopiedNotice = self.showCopiedNotice.bind( self );
		self.showWishlistURLNotice = self.showWishlistURLNotice.bind( self );

		// Events.
		$( document.body ).on( 'click.wcboost-wishlist', '.wcboost-wishlist-share-link', { wishlistShareHandler: self }, self.onClickShareLink );
	}

	WishlistShareHandler.prototype.onClickShareLink = function( event ) {
		var self = event.data.wishlistShareHandler,
			url = event.currentTarget.href,
			social = event.currentTarget.dataset.social;

		// Do nothing if sending emails.
		if ( 'email' === social ) {
			return;
		}

		// Copy wishlist page URL to clipboard.
		if ( 'link' === social ) {
			event.preventDefault();

			try {
				navigator.clipboard.writeText( url ).then( self.showCopiedNotice );
			} catch ( e ) {
				self.showWishlistURLNotice( url );
			}
		} else {
			var opened = self.openSocialShareIframe( url );

			if ( opened ) {
				event.preventDefault();
			}
		}
	}

	WishlistShareHandler.prototype.openSocialShareIframe = function( url ) {
		var width = 500,
			height = 450,
			top = (window.screen.height / 2) - ((height / 2) + 50),
			left = (window.screen.width / 2) - ((width / 2) + 10),
			features = "status=no,resizable=yes,width=" + width + ",height=" + height + ",left=" + left + ",top=" + top + ",screenX=" + left + ",screenY=" + top + ",toolbar=no,menubar=no,scrollbars=no,location=no,directories=no";

		if ( window.screen.width <= width ) {
			return false;
		}

		var sharer = window.open( url, 'sharer', features );
		sharer.focus();

		return true;
	}

	WishlistShareHandler.prototype.showCopiedNotice = function() {
		if ( ! this.copiedNotice ) {
			this.copiedNotice = new WCBoostNotice(
				$( '<div class="wcboost-wishlist-link-copied-notice wcboost-wishlist-share-notice" />' ).text( wcboost_wishlist_params.i18n_link_copied_notice ),
				{
					type: 'message'
				}
			);
		}

		this.copiedNotice.show();
	}

	WishlistShareHandler.prototype.showWishlistURLNotice = function( url ) {
		if ( ! this.urlNotice ) {
			var $notice = $( '<div class="wcboost-wishlist-share-notice" />' );

			$notice.append( '<input type="text" value="" />' );
			$notice.append( '<span class="wcboost-wishlist-share-notice__close" role="button">' + wcboost_wishlist_params.i18n_close_button_text + '</span>' );

			var notice = new WCBoostNotice( $notice, {
				duration: -1,
				type: 'info'
			});

			$notice.on( 'click', '.wcboost-wishlist-share-notice__close', function() {
				notice.hide();
			} );

			this.urlNotice = notice;
		}

		this.urlNotice.show();
		this.urlNotice.$notice.find( 'input' ).val( url ).focus();
	}

	/**
	 * Wishlist widget class
	 */
	var WCBoostWishlistWidget = function() {
		var self = this;

		self.selectors = {
			widget: '.wcboost-wishlist-widget',
			content: '.wcboost-wishlist-widget-content',
		};

		self.checkWidgetVisibility = self.checkWidgetVisibility.bind( self );

		$( document.body )
			.on( 'click', self.selectors.content + ' a.remove', { wishlistWidget: self }, self.removeItem )
			.on( 'wishlist_fragments_loaded', { wishlistWidget: self }, self.checkWidgetVisibility );

		self.checkWidgetVisibility();
	}

	WCBoostWishlistWidget.prototype.checkWidgetVisibility = function() {
		var self = this;
		var $widgets = $( self.selectors.widget );

		if ( ! $widgets.length ) {
			return;
		}

		$widgets.each( function() {
			var $currentWidget = $( this );

			// Check if the option to hide if empty is selected.
			if ( ! $currentWidget.find( '.wcboost-wishlist-widget__hide-if-empty' ).length ) {
				return;
			}

			// Check if has products.
			if ( $currentWidget.find( '.wcboost-wishlist-widget__products' ).length ) {
				$currentWidget.show();
			} else {
				$currentWidget.hide();
			}
		} );
	}

	WCBoostWishlistWidget.prototype.removeItem = function( event ) {
		event.preventDefault();

		var self = event.data.wishlistWidget;
		var params = new URLSearchParams( event.currentTarget.search );
		var data = {
			item_key: params.get( 'remove-wishlist-item' ),
			_wpnonce: params.get( '_wpnonce' ),
		};

		if ( ! data.item_key ) {
			return;
		}

		var $widget = $( self.selectors.widget );

		$.post( {
			url: woocommerce_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'remove_wishlist_item' ),
			data: data,
			dataType: 'json',
			beforeSend: function() {
				block( $widget );
			},
			success: function( response ) {
				if ( ! response.success ) {
					return;
				}

				var fragments = response.data.fragments;

				$( document.body )
					.trigger( 'removed_from_wishlist', [ null, fragments ] )
					.trigger( 'wishlist_item_removed', [ response.data ] );
			},
			complete: function() {
				unblock( $widget );
			}
		} );
	}

	$( function() {
		new AddToWishlistHandler();
		new WCBoostWishlist( $( '.wcboost-wishlist-form' ) );
		new WishlistShareHandler();
		new WCBoostWishlistWidget();
	} );
} )( jQuery );
