/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n'
import domReady from '@wordpress/dom-ready';

/**
 * Third party dependencies
 */
import Tabby from 'tabbyjs'; // https://github.com/cferdinandi/tabby

/**
 * Internal dependencies
 */
import saveAlerts from './components/save-alerts';
import entityEditing from './components/entity-editing';

/**
 * Web Components
 */
import './components/ajax-form';
import './components/ajax-html';
import './components/auto-complete';
import './components/custom-tag-lists';

// Rule Form Extension for WooCommerce conditions
import ruleFormExtension from './components/rule-form-extension';

// Data Export Form functionality
import dataExportForm from './components/data-export';

domReady( () => {

	if ( window.pwpSettings && '' !== window.pwpSettings?.kb ) {
		// Mark admin menu item to open in new window
		document.querySelector(`ul#adminmenu a[href=\'${window.pwpSettings.kb}\']`)?.setAttribute("target", "_blank");
	}

	// Look for entity forms (segments, etc.) and rule forms
	const entityForm = document.querySelector('form[data-pwp]');
	if ( entityForm ) {
		entityEditing( entityForm );
	}

	// Initialize data export form functionality
	const dataExportFormElement = document.querySelector('.export-form-section form');
	if ( dataExportFormElement ) {
		dataExportForm( dataExportFormElement );
	}

	// Ensure any dialogs have close buttons that close.
	var dialogs = document.querySelectorAll( 'dialog.dialog' );
	if ( 0 !== dialogs.length ) {
		dialogs.forEach( dialog => {
			dialog.addEventListener('click', function(e) {
				// Clicking 'outside' of the dialog causes the target to be the dialog
				if ( e.target.matches( 'dialog' ) ) {
					dialog.close( 'close' );
					e.stopPropagation();
					return;
				}
				// Track any button specifically marked to close the dialog
				const but = e.target.closest('button');
				if ( but && but.matches( 'button[value=close]' ) ) {
					dialog.close( 'close' );
					e.stopPropagation();
					return;
				}
			});
		});
	}

	// Ensure any modal links open the corresponding modal. Track via propagated link.
	document.addEventListener( 'click', function(event) {
		var btnLink = event.target.closest( '[data-show-modal]' );
		if (!btnLink) return;
		const target = btnLink.getAttribute( 'data-show-modal' );
		const dialog = document.querySelector( target );

		if ( window.HTMLDialogElement !== undefined && dialog ) {
			// Some modals have a dynamic action (delete etc), so update the forms' action first.
			if ( dialog.hasAttribute( 'data-url-action' ) ) {
				let url;
				// Prioritise a links href
				if ( btnLink.hasAttribute( 'href' ) ) {
					url = btnLink.getAttribute( 'href' );
				}
				// except a button could instead use a form action
				if ( btnLink.hasAttribute( 'data-form-action' ) ) {
					url = btnLink.getAttribute( 'data-form-action' );
				}
				if ( url ) {
					dialog.querySelector( 'form' ).setAttribute( 'action', url );
				}
			}
			// Category Edit modal form has additional inputs to update.
			if ( '#editCategoryModal' === target ) {
				// Update the edit modal with Category specific data
				const url = btnLink.getAttribute( 'href' ),
					catID = btnLink.getAttribute( 'data-id' ),
					catName = btnLink.getAttribute( 'data-name' );
				dialog.querySelector( 'form' ).setAttribute( 'action', url );
				dialog.querySelector( '[name="personalizewp_form[id]"]' ).value = catID;
				dialog.querySelector( '[name="personalizewp_form[name]"]' ).value = catName;
			}
			// Prevent any normal link
			event.preventDefault();
			dialog.showModal();
		}
	});

	// Newsletter signup additional processing.
	const newsletterSignup = document.querySelector( 'ajax-form#newsletter-signup' );
	if ( newsletterSignup ) {
		newsletterSignup.addEventListener( 'pwp-ajax-form:submit-before', (event) => {
			const fieldErrors = newsletterSignup.querySelectorAll('.field-error');
			// Remove classes and rehide any errors in form
			fieldErrors.forEach( fieldError => {
				fieldError.classList.remove('field-error');
				const inputError = fieldError.querySelector('.input-error');
				inputError.hidden = true;
			});
		} );
		newsletterSignup.addEventListener( 'pwp-ajax-form:error', (event) => {
			const formErrors = event.detail?.errors ?? [];
			if (!formErrors.length) return;
			formErrors.forEach( inputName => {
				const inputField = newsletterSignup.querySelector( `input[name="${inputName}"]`).closest('.field');
				const inputError = inputField.querySelector('.input-error');
				inputField.classList.add('field-error');
				inputError.hidden = false;
			});
		} );
		newsletterSignup.addEventListener( 'pwp-ajax-form:success', (event) => {
			// Toggle submit buttons visibility, if used
			const buttons = newsletterSignup.querySelectorAll('.actions button');
			buttons.forEach(button => {
				button.hidden = ! button.hidden;
			});
		});
	}

	/**
	 * Submit formdata via fetch API to ajax URL
	 * Fetch API is modern, but admin-ajax expects old-style url formatted data.
	 * @param {FormData} formdata
	 */
	const sendAjax = async function( formdata ) {

		// Create a new URLSearchParams object
		let params = new URLSearchParams();
		// Add the form data
		for (let [key, val] of formdata) {
			params.append(key, val);
		}

		const response = await fetch(pwpSettings.url, {
			method: "POST",
			headers: {
				'Accept': 'application/json, */*;q=0.1',
				'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8',
				'X-Requested-With': 'XMLHttpRequest',
			},
			// Set the FormData instance as the request body
			body: params.toString(),
		});
		const data = await response.json();
		if ( response.ok ) {
			return data;
		}
		return false;
	}

	/**
	 * Dismiss Permanent Notices
	 */
	const notices = document.querySelectorAll( '.notice[data-dismiss-type]' );
	if ( 0 !== notices.length ) {
		notices.forEach( notice => {
			notice.addEventListener( 'click', function(e) {
				if ( ! e.target.matches( 'button' ) ) {
					return;
				}
				e.stopPropagation();
				const type = notice.getAttribute( 'data-dismiss-type' );
				const data = new FormData();
				data.append( 'action', `pwp_dismiss_${type}_message` );
				data.append( '_ajax_nonce', pwpSettings.nonce );
				sendAjax( data );
				// Notice will remove due to WP JS.
			});
		});
	}

	/**
	 * Check and initialise any tabs, such as those on Settings
	 */
	if (document.querySelector('.pwp-page [data-tabs]')) {
		const tabs = new Tabby('.pwp-page [data-tabs]', {
			idPrefix: 'pwp_', // The prefix to add to tab element IDs if they don't already have one
		});
		document.addEventListener('tabby', function (event) {
			event.detail.tab.classList.add('is-active');
			event.detail.previousTab.classList.remove('is-active');
		}, false);
	}

	// Trigger alert after making form input changes that are unsaved.
	saveAlerts();

	/**
	 * Hack to update the value input with the correct placeholder depending on the condition measure.
	 *
	 * ToDo: Remove this, instead use better form condition action/filters
	 */
	const setValuePlaceholder = ( condition ) => {
		const measureSelect = condition.querySelector( '.conditions-measure' );
		const measureValue = measureSelect?.value;
		const valueInput = condition.querySelector( '.text-field-wrapper .field-value-text' );
		let valuePlaceholder = null;

		switch ( measureValue ) {
			case 'woocommerce_time_since_last_order':
				valuePlaceholder = __( 'Enter number of days', 'personalizewp' );
				break;
		}
		if ( valuePlaceholder && valueInput ) {
			if ( ! valueInput.getAttribute( 'data-initial-placeholder' ) ) {
				valueInput.setAttribute( 'data-initial-placeholder', valueInput.placeholder );
			}
			valueInput.placeholder = valuePlaceholder;
		}
	};

	// Initialize rule form extension for rule editing pages
	const ruleForm = document.querySelector('#pwp-form');
	if ( ruleForm ) {
		ruleFormExtension( ruleForm );

		// Update the HTML as we can't do that directly in PHP.
		const conditions = ruleForm.querySelectorAll( '.condition' );
		conditions.forEach( setValuePlaceholder );
		// Additional hack, to handle condition type changes
		ruleForm.addEventListener( 'change', ( event ) => {
			if ( ! event.target.classList.contains( 'conditions-measure' ) ) {
				return;
			}
			const condition = event.target.closest( '.condition' );
			if ( condition ) {
				setValuePlaceholder( condition );
			}
		});
	}
});
