(function ($) {
	$( window ).on( 'elementor/frontend/init', () => {
		class WooCartWidget extends elementorModules.frontend.handlers.Base {
			getDefaultSettings() {
				return {
					selectors: {
						quantityInput: '.qty',
						updateCartButton: 'button[name=update_cart]',
					},
					// How long to wait after the last keystroke before the cart
					// is submitted.
					updateDelay: 1500,
				};
			}

			getDefaultElements() {
				return {};
			}

			bindEvents() {
				const elementSettings = this.getElementSettings(),
					selectors = this.getSettings( 'selectors' );

				if ( 'yes' !== elementSettings.update_cart_automatically ) {
					return;
				}

				// Delegated from the widget root and namespaced, so the handler
				// survives WooCommerce replacing the table markup and can be
				// taken back off again on its own.
				this.$element.on( 'input.ppWooCart', selectors.quantityInput, () => this.updateCart() );
			}

			unbindEvents() {
				this.$element.off( 'input.ppWooCart' );
				clearTimeout( this.updateTimeout );
			}

			updateCart() {
				const selectors = this.getSettings( 'selectors' );

				/*
				 * The pending timer is held on the instance rather than in a
				 * local. A local is a fresh binding on every call, so
				 * clearTimeout() never had anything to clear and every
				 * keystroke queued its own submit: typing "12" submitted a
				 * quantity of 1 a second and a half after the first keystroke
				 * and reloaded the page under the shopper.
				 */
				clearTimeout( this.updateTimeout );

				this.updateTimeout = setTimeout( () => {
					this.$element.find( selectors.updateCartButton ).trigger( 'click' );
				}, this.getSettings( 'updateDelay' ) );
			}

			onElementChange( propertyName ) {
				// Rebinding here is what lets the control skip a server side
				// re-render. Toggling it otherwise has to run the whole
				// [woocommerce_cart] shortcode again, cart totals and cross
				// sell product loop included.
				if ( 'update_cart_automatically' === propertyName ) {
					this.unbindEvents();
					this.bindEvents();
				}
			}

			onDestroy() {
				// The editor tears handlers down and rebuilds them on every
				// re-render. A timer left running would submit the cart against
				// a widget that is no longer on the page.
				this.unbindEvents();

				if ( super.onDestroy ) {
					super.onDestroy();
				}
			}
		}

		elementorFrontend.elementsHandler.attachHandler( 'pp-woo-cart', WooCartWidget );
	} );
})(jQuery);
