/**
 *
 * Shoptimizer quantity custom script
 *
 * @package Shoptimizer
 */

let changEv   = new Event( 'change' );
let sidebarEl = [];
let timerId;
let miniItems;
const shopWidget = document.querySelector( '.widget_shopping_cart' );

const shoptimizerDelayFunction = function( func, delay ) {
	clearTimeout( timerId );
	timerId = setTimeout( func, delay );
};
function shoptimizerInitMiniCartQty() {
	if ( ! shopWidget ) {
		return;
	}
	sidebarEl = [];
	miniItems = shopWidget.querySelectorAll( '.shoptimizer-custom-quantity-mini-cart' );
	miniItems.forEach(
		function( item ) {
			sidebarEl.push(
				{
					qtInput: item.querySelector( 'input' ),
					qtButtons: Array.from( item.querySelectorAll( '.shoptimizer-custom-quantity-mini-cart_button' ) )
				}
			);
		}
	);
	sidebarEl.forEach(
		function( item ) {
			item.qtButtons.forEach(
				function( btn ) {
					btn.addEventListener( 'click', shoptimizerEachSideBtnListener );
				}
			);
			item.qtInput.addEventListener( 'change', shoptimizerUpdateMiniCart );
		}
	);
}
/**
 * Return the number of decimal places in a numeric string, used so we can
 * round incremented values to the precision defined by the `step` attribute
 * (important for plugins like ATUM that allow decimal stock quantities).
 */
function shoptimizerDecimalPlaces( numStr ) {
	if ( ! numStr ) {
		return 0;
	}
	const parts = String( numStr ).split( '.' );
	return parts[1] ? parts[1].length : 0;
}
function shoptimizerEachSideBtnListener() {
	const item    = sidebarEl.find( ( el ) => el.qtButtons.includes( this ) );
	let value     = parseFloat( item.qtInput.value );
	let stepAttr  = item.qtInput.getAttribute( 'step' );
	let step      = parseFloat( stepAttr );
	if ( isNaN( step ) || step <= 0 ) {
		step = 1;
	}
	let minValue  = parseFloat( item.qtInput.getAttribute( 'min' ) );
	let maxValue  = parseFloat( item.qtInput.getAttribute( 'max' ) );
	let fallback  = ! isNaN( minValue ) && minValue > 0 ? minValue : step;
	value         = isNaN( value ) ? fallback : value;
	const decimals = Math.max( shoptimizerDecimalPlaces( stepAttr ), shoptimizerDecimalPlaces( item.qtInput.value ) );
	if ( this.classList.contains( 'quantity-up' ) ) {
		value += step;
		if ( ! isNaN( maxValue ) && value > maxValue ) {
			value = maxValue;
		}
	} else {
		value -= step;
		if ( ! isNaN( minValue ) && value < minValue ) {
			value = minValue;
		}
		// Never go below the step value (or min, if min is positive).
		if ( value < fallback ) {
			value = fallback;
		}
	}
	// Round to the precision of the step to avoid floating-point artefacts
	// like 0.1 + 0.2 = 0.30000000000000004.
	if ( decimals > 0 ) {
		value = parseFloat( value.toFixed( decimals ) );
	}
	if ( parseFloat( item.qtInput.value ) !== value ) {
		item.qtInput.value = value;
		item.qtInput.dispatchEvent( changEv );
	}
}
function shoptimizerUpdateMiniCart() {
	shoptimizerDelayFunction(
		function() {
			var formData = new FormData();
			miniItems    = document.querySelectorAll( '.shoptimizer-custom-quantity-mini-cart' );
			miniItems.forEach(
				function( item ) {
					let input   = item.querySelector( 'input' );
					// Use parseFloat so decimal quantities (e.g. ATUM) are preserved.
					let qty     = parseFloat( input.value );
					qty         = isNaN( qty ) ? 1 : qty;
					let itemKey = input.getAttribute( 'data-cart_item_key' );
					formData.append( 'data[' + itemKey + ']', qty );
				}
			);
			formData.append( 'action', 'cg_shoptimizer_update_mini_cart' );
			var ajax_loader = document.querySelector( '#ajax-loading' );
			if ( ajax_loader ) {
				ajax_loader.style.display = 'block';
			}
			fetch(
				woocommerce_params.ajax_url,
				{
					method: 'POST',
					body: formData
				}
			).then(
				response => response.json()
			).then(
				function( json ) {
					var wcfragment = new Event( 'wc_fragment_refresh' );
					document.body.dispatchEvent( wcfragment );
					var wccart = document.querySelectorAll( 'form.woocommerce-cart-form input.qty, form.woocommerce-checkout' );
					if ( 0 < wccart.length ) {
						window.location.reload();
					}
				}
			);
		},
		600
	);
}
jQuery( 'body' ).on( 'wc_fragments_refreshed wc_fragments_loaded', shoptimizerInitMiniCartQty );
shoptimizerInitMiniCartQty();
