/**
 * @package Polylang-Pro
 */

const { addAction } = wp.hooks;

const pllMachineTranslation = {
	/**
	 * Init.
	 */
	init: () => {
		if ( document.readyState !== 'loading' ) {
			pllMachineTranslation.ajaxButton.attachEvent();
			pllMachineTranslation.dataUsage.fetchData();
		} else {
			document.addEventListener( 'DOMContentLoaded', pllMachineTranslation.ajaxButton.attachEvent );
			document.addEventListener( 'DOMContentLoaded', pllMachineTranslation.dataUsage.fetchData );
		}
		addAction( 'pll_settings_saved', 'polylang-pro', pllMachineTranslation.saveSettings.highlightRow );
	},

	/**
	 * Resets a field's row.
	 *
	 * @param {HTMLElement} fieldRow Field's row.
	 */
	resetFieldRow: ( fieldRow ) => {
		fieldRow.querySelectorAll( '.pll-message-shown' ).forEach( ( el ) => {
			el.classList.remove( 'pll-message-shown' );
		} );
		fieldRow.classList.remove( 'notice-success', 'notice-warning', 'notice-error', 'notice-alt' );
		fieldRow.querySelectorAll( '.pll-error-message-text' ).forEach( ( el ) => {
			el.textContent = '';
		} );
	},

	/**
	 * Displays an error message under the field by adding HTML classes.
	 *
	 * @param {HTMLElement} fieldRow     Field's row.
	 * @param {String}      messageClass HTML class of the error message to display.
	 * @param {String}      type         Type of the error: `'error'` or `'warning'`.
	 */
	displayErrorMessage: ( fieldRow, messageClass, type = 'error' ) => {
		if ( messageClass ) {
			fieldRow.querySelectorAll( '.' + messageClass ).forEach( ( el ) => {
				el.classList.add( 'pll-message-shown' );
			} );
		}
		fieldRow.classList.add( 'notice-' + type, 'notice-alt' );
	},

	ajaxButton: {
		/**
		 * Attaches an event to `.pll-ajax-button` buttons to trigger AJAX requests.
		 */
		attachEvent: () => {
			document.querySelectorAll( '.pll-ajax-button' ).forEach( ( el ) => {
				el.addEventListener( 'click', ( event ) => {
					const button    = event.target;
					const action    = button.getAttribute( 'data-action' );
					const nonce     = button.getAttribute( 'data-nonce' );
					const fieldRow  = button.closest( 'tr' );
					const errorElms = fieldRow.querySelectorAll( '.pll-error-message-text' );

					if ( ! action || ! nonce || ! fieldRow || ! errorElms.length || button.getAttribute( 'disabled' ) ) {
						return;
					}

					const urlParams = { 'action': action, '_pll_nonce': nonce, 'pll_ajax_settings': 1 };
					fieldRow.querySelectorAll( '[data-name]' ).forEach( ( el ) => {
						urlParams[ el.getAttribute( 'data-name' ) ] = el.value;
					} );
					const url = wp.url.addQueryArgs( ajaxurl, urlParams );

					button.setAttribute( 'disabled', 'disabled' );
					pllMachineTranslation.resetFieldRow( fieldRow );

					fetch( url ).then( ( response ) => {
						return response.json();
					} ).then( ( json ) => {
						button.removeAttribute( 'disabled' );

						if ( json.success ) {
							fieldRow.classList.add( 'notice-success', 'notice-alt' );
						} else {
							errorElms[0].textContent = json.data && json.data.message ? json.data.message : '';
							pllMachineTranslation.displayErrorMessage( fieldRow, json.data ? json.data.message_class : '' );
						}
					} ).catch( () => {
						button.removeAttribute( 'disabled' );
						fieldRow.classList.add( 'notice-error', 'notice-alt' );
					} );
				} );
			} );
		}
	},

	saveSettings: {
		/**
		 * Highlights a settings row in case of error when the settings are saved.
		 * Hooked to `'pll_settings_saved'`.
		 *
		 * @param {Object}      response The response from the AJAX call.
		 * @param {HTMLElement} tr       The HTML element containing the module's fields.
		 */
		highlightRow: ( response, tr ) => {
			switch ( response.what ) {
				case 'success':
					tr.querySelectorAll( '.notice-alt, .pll-message-shown' ).forEach( ( el ) => {
						el.classList.remove( 'notice-success', 'notice-warning', 'notice-error', 'notice-alt', 'pll-message-shown' );
					} );
					break;

				case 'error':
					const noticeData = pllMachineTranslation.saveSettings.getNoticeData( response.data );

					if ( ! noticeData.fieldId ) {
						break;
					}

					const field = document.getElementById( noticeData.fieldId );

					if ( ! field ) {
						break;
					}

					const fieldRow = field.closest( 'tr' );

					if ( ! fieldRow ) {
						break;
					}

					pllMachineTranslation.resetFieldRow( fieldRow );
					pllMachineTranslation.displayErrorMessage( fieldRow, noticeData.messageClass, noticeData.type );
					break;
			}
		},

		/**
		 * Returns the data contained in the HTML classes of the given element.
		 *
		 * @param {String} htmlString HTML string.
		 * @returns {Object}
		 */
		getNoticeData: ( htmlString ) => {
			const div = document.createElement( 'div' );
			div.innerHTML = htmlString.trim(); // phpcs:ignore WordPressVIPMinimum.JS.InnerHTML.Found
			return {
				type:         pllMachineTranslation.saveSettings.find( div.firstChild.className, 'notice-(success|warning|error)', 'error' ),
				fieldId:      pllMachineTranslation.saveSettings.find( div.firstChild.className, 'pll-field-id-([^\\s]+)', '' ), // See `Settings\Deepl::is_api_key_valid()` and `Module_Settings::update()`.
				messageClass: pllMachineTranslation.saveSettings.find( div.firstChild.className, 'pll-message-class-([^\\s]+)', '' ) // See `Settings\Deepl::is_api_key_valid()` and `Module_Settings::update()`.
			};
		},

		/**
		 * Returns the part of the given string matching the given pattern.
		 *
		 * @param {String} string  A string.
		 * @param {String} pattern A regex pattern.
		 * @param {String} def     String to return if nothing is found.
		 * @returns {String}
		 */
		find: ( string, pattern, def ) => {
			const matches = ( ' ' + string + ' ' ).match( new RegExp( '\\s' + pattern + '\\s' ) );
			return matches && matches[1] ? matches[1] : def;
		}
	},

	dataUsage: {
		fetchData: () => {
			document.querySelectorAll( '.pll-progress-bar-wrapper' ).forEach( ( el ) => {
				const action   = el.getAttribute( 'data-action' );
				const nonce    = el.getAttribute( 'data-nonce' );
				const spinner  = el.querySelectorAll( '.spinner' ).item( 0 );
				const progress = el.querySelectorAll( 'div' ).item( 0 );

				if ( ! action || ! nonce || ! spinner || ! progress || ! el.parentElement ) {
					return;
				}

				const description = el.parentElement.querySelectorAll( '.description' ).item( 0 );

				if ( ! description ) {
					return;
				}

				const urlParams = { 'action': action, '_pll_nonce': nonce, 'pll_ajax_settings': 1 };
				const url       = wp.url.addQueryArgs( ajaxurl, urlParams );

				fetch( url ).then( ( response ) => {
					return response.json();
				} ).then( ( json ) => {
					if ( ! json.success || ! json.data.percent ) {
						/*
						 * 2 cases:
						 * - Error while retrieving the data: display the error message.
						 * - The character limit is 0: display only the character count.
						 */
						el.remove();
						description.textContent = json.data.message;
						return;
					}

					// Display a graphic.
					el.replaceChild( document.createTextNode( json.data.percent_formatted ), spinner );
					progress.textContent    = json.data.percent_formatted;
					progress.style.width    = json.data.percent;
					description.textContent = json.data.message;
				} ).catch( () => {
					el.closest( 'tr' ).remove();
				} );
			} );
		}
	}
};

pllMachineTranslation.init();


