import { parse, format, templateParser, parseDigit, templateFormatter } from 'input-format';
import { AsYouType } from 'libphonenumber-js';

/**
 * @function edit
 * @description Edits text based on the operation.
 *              Copied from the original function `edit` from `input-format` package.
 *              The original function is not exported, so it was copied here.
 *
 * @param {string} value     The value to edit.
 * @param {number} caret     The caret position.
 * @param {string} operation The operation to perform, one of `Backspace` or `Delete`.
 *
 * @return {object} The edited value and the caret position.
 */
export const edit = ( value, caret, operation ) => {
	// Edits text `value` (if `operation` is passed) and repositions the `caret` if needed.
	//
	// Example:
	//
	// value - '88005553535'
	// caret - 2 // starting from 0; is positioned before the first zero
	// operation - 'Backspace'
	//
	// Returns
	// {
	// 	value: '8005553535'
	// 	caret: 1
	// }
	//
	// Currently supports just 'Delete' and 'Backspace' operations
	//
	switch ( operation ) {
		case 'Backspace':
			// If there exists the previous character,
			// then erase it and reposition the caret.
			if ( caret > 0 ) {
				// Remove the previous character
				value = value.slice( 0, caret - 1 ) + value.slice( caret );
				// Position the caret where the previous (erased) character was
				caret--;
			}
			break;

		case 'Delete':
			// Remove current digit (if any)
			value = value.slice( 0, caret ) + value.slice( caret + 1 );
			break;
	}

	return { value, caret };
};

/**
 * @function parseDigitWithPlus
 * @description Parses a digit with a plus sign.
 *
 * @since 5.5.0
 *
 * @param {boolean} international Whether the phone number is in international format.
 *
 * @return {Function} The function to parse a digit with a plus sign.
 */
export const parseDigitWithPlus = ( international ) => ( character, value ) => {
	// Leading plus is allowed
	if ( international && character === '+' && ! value ) {
		return character;
	}
	// Digits are allowed
	return parseDigit( character );
};

/**
 * @function getFormattedInputText
 * @description Gets the formatted input text.
 *              Modified from the original function `formatInputText` from `input-format` package.
 *
 * @since 5.5.0
 *
 * @param {string}           inputValue    The input value.
 * @param {number}           caretPosition The caret position.
 * @param {string}           country       The country code.
 * @param {boolean}          international Whether the phone number is in international format.
 * @param {string|undefined} operation     The operation to perform, one of `Backspace` or `Delete`.
 *
 * @return {object} The formatted input text, caret position, and the AsYouType instance.
 */
export const getFormattedInputText = (
	inputValue,
	caretPosition,
	country,
	international,
	operation,
) => {
	const asYouType = new AsYouType( country );
	asYouType.input( inputValue );

	const parser = templateParser( asYouType.getTemplate(), parseDigitWithPlus( international ) );

	// Parse input value.
	// Get the `value` and `caret` position.
	let { value, caret } = parse( inputValue, caretPosition, parser );

	// If a user performed an operation ("Backspace", "Delete")
	// then apply that operation and get the new `value` and `caret` position.
	if ( operation ) {
		const newValueAndCaret = edit( value, caret, operation );

		value = newValueAndCaret.value;
		caret = newValueAndCaret.caret;
	}

	asYouType.reset();
	asYouType.input( value );
	const formatter = templateFormatter( asYouType.getTemplate(), 'x', true );

	// Format the `value` and reposition the caret accordingly.
	return {
		asYouType,
		formatted: format( value, caret, formatter ),
	};
};
