import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { forwardRef, useCallback, useMemo } from 'react';
import VisuallyHiddenText from '../VisuallyHiddenText';
import FormField from '../FormField';
import { useConfiguration, useConsolidatedRef, useI18n, useInputFormatter, usePrevious, useTestIds, useUID } from '../../hooks';
import { getCleanedValue, getDecimalSign, getDecrementedValue, getIncrementedValue } from '../Number/utils';
import { createClassName, withTestIds } from '../../utils';
import StyledCurrencyInput from './CurrencyInput.styles';
import { getCurrencyMinimumFractionDigits, getFormattedValue, isValidCurrency } from './utils';
import { getCurrencyInputTestIds } from './Currency.test-ids';
const CurrencyInput = forwardRef(function CurrencyInput(props, ref) {
    const uid = useUID();
    const { testId, id = uid, status, label, labelHidden, info, required, disabled, readOnly, additionalInfo, value: valueProp = '', onChange, onBlur, onFocus, onResolveSuggestion, currencyISOCode, showDecimal = true, showGroupSeparators = true, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER, step = 1, alwaysShowISOCode = false, maximumFractionDigits = 0, className, ...restProps } = props;
    const descriptionId = useUID();
    const testIds = useTestIds(testId, getCurrencyInputTestIds);
    const { locale } = useConfiguration();
    const t = useI18n();
    const inputRef = useConsolidatedRef(ref);
    const validCurrencyISOCode = useMemo(() => (currencyISOCode && isValidCurrency(currencyISOCode) ? currencyISOCode : undefined), [currencyISOCode]);
    const minimumFractionDigits = useMemo(() => getCurrencyMinimumFractionDigits(locale, validCurrencyISOCode), [locale, validCurrencyISOCode]);
    const numberOfDecimals = showDecimal
        ? Math.max(maximumFractionDigits, minimumFractionDigits)
        : 0;
    const decimalSign = useMemo(() => getDecimalSign(locale, {
        numberingSystem: 'latn',
        style: validCurrencyISOCode ? 'currency' : undefined,
        currency: validCurrencyISOCode
    }), [locale, validCurrencyISOCode]);
    // on initial render only pad the value with 0 if necessary
    const rendered = usePrevious(true);
    let value = valueProp;
    if (!rendered && validCurrencyISOCode && !Number.isNaN(parseFloat(value))) {
        const [integer, fraction = ''] = value.split('.');
        value = `${integer}.${fraction.padEnd(numberOfDecimals, '0')}`;
    }
    const formatValue = useCallback((number) => {
        return getFormattedValue(number, locale, validCurrencyISOCode, {
            showGroupSeparators,
            showAs: alwaysShowISOCode ? 'code' : 'symbol',
            numberOfDecimals
        });
    }, [alwaysShowISOCode, numberOfDecimals, showGroupSeparators, locale, validCurrencyISOCode]);
    const onInputChange = (e) => {
        const inputValue = e.target.value;
        const cleanedInputValue = getCleanedValue(inputValue, decimalSign, numberOfDecimals);
        if (cleanedInputValue === value)
            return;
        onChange(cleanedInputValue);
    };
    const onKeyDown = (e) => {
        if (readOnly)
            return;
        const input = e.currentTarget;
        switch (e.key) {
            case 'ArrowUp':
                e.preventDefault();
                onChange(getIncrementedValue(value, min, max, step));
                break;
            case 'ArrowDown':
                e.preventDefault();
                onChange(getDecrementedValue(value, min, max, step));
                break;
            case decimalSign:
                if (!showDecimal)
                    e.preventDefault();
                if (input.value.includes(decimalSign)) {
                    if (input.selectionStart && input.value.charAt(input.selectionStart) === decimalSign) {
                        input.setSelectionRange(input.selectionStart + 1, input.selectionStart + 1);
                    }
                    e.preventDefault();
                }
                else if (input.selectionStart !== null &&
                    !input.value.charAt(input.selectionStart - 1).match(/\d/)) {
                    onChange(getCleanedValue(`${input.value}0${decimalSign}`, decimalSign, numberOfDecimals));
                    e.preventDefault();
                }
                break;
            case '-':
                if (value.startsWith('-'))
                    e.preventDefault();
                break;
            default:
        }
    };
    const onInputFocusEvent = (e) => {
        let parsableValue = value;
        if (validCurrencyISOCode && !Number.isNaN(parseFloat(value))) {
            const [integer, fraction = ''] = value.split('.');
            parsableValue = `${integer}.${fraction.padEnd(numberOfDecimals, '0')}`;
        }
        if (e.type === 'focus')
            onFocus?.(parsableValue);
        else {
            if (parsableValue !== value) {
                onChange(parsableValue);
            }
            onBlur?.(parsableValue);
        }
    };
    const formattedValue = useInputFormatter(inputRef, value, formatValue, `0-9${decimalSign}-`);
    const Comp = (_jsxs(_Fragment, { children: [_jsx(StyledCurrencyInput, { "data-testid": testIds.control, onChange: onInputChange, id: id, readOnly: readOnly, required: required, disabled: disabled, status: status, ...restProps, onResolveSuggestion: onResolveSuggestion, inputMode: 'numeric', ref: inputRef, value: formattedValue, onKeyDown: onKeyDown, onFocus: onInputFocusEvent, onBlur: onInputFocusEvent, "aria-describedby": validCurrencyISOCode ? descriptionId : undefined, className: createClassName('currency-input', className) }), validCurrencyISOCode && (_jsx(VisuallyHiddenText, { id: descriptionId, "aria-hidden": true, children: t('measured_in', [validCurrencyISOCode]) }))] }));
    return label ? (_jsx(FormField, { testId: testIds, label: label, labelHidden: labelHidden, id: id, info: info, readOnly: readOnly, status: status, required: required, disabled: disabled, additionalInfo: additionalInfo, onResolveSuggestion: onResolveSuggestion, children: Comp })) : (Comp);
});
export default withTestIds(CurrencyInput, getCurrencyInputTestIds);
//# sourceMappingURL=CurrencyInput.js.map