import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { cloneElement, useEffect, forwardRef, useState, useRef, Children } from 'react';
import styled, { css } from 'styled-components';
import { rgba } from 'polished';
import { defaultThemeProp } from '../../theme';
import Flex, { StyledFlex } from '../Flex';
import Actions from '../Actions';
import { useConsolidatedRef, useI18n, useLiveLog, useTestIds, useUID } from '../../hooks';
import Label, { StyledLabel } from '../Label';
import { calculateFontSize, getHoverColors, readableColor, readableHue } from '../../styles';
import VisuallyHiddenText from '../VisuallyHiddenText';
import { getFocusables, tryCatch, withTestIds, createClassName } from '../../utils';
import Button from '../Button';
import Icon, { registerIcon } from '../Icon';
import * as warnSolidIcon from '../Icon/icons/warn-solid.icon';
import * as diamondMinusIcon from '../Icon/icons/diamond-minus.icon';
import * as checkIcon from '../Icon/icons/check.icon';
import AdditionalInfo, { StyledAdditionalInfo } from '../AdditionalInfo';
import { StyledRadioCheck, StyledRadioCheckInput } from '../RadioCheck/RadioCheck';
import { getFormFieldTestIds } from './FormField.test-ids';
registerIcon(warnSolidIcon, diamondMinusIcon, checkIcon);
const StyledStatusIcon = styled(Icon)(({ theme, status }) => {
    return css `
    height: 1em;
    width: 1em;
    color: ${tryCatch(() => readableHue(theme.components['form-field'][status]['status-color'], theme.base.palette['primary-background']), () => theme.components['form-field'][status]['status-color'])};
    vertical-align: baseline;
  `;
});
StyledStatusIcon.defaultProps = defaultThemeProp;
const StyledClearButton = styled(Button)(({ theme }) => {
    return css `
    margin-block-start: calc(${theme.base.spacing} / 2);
    align-self: start;
  `;
});
StyledClearButton.defaultProps = defaultThemeProp;
export const StyledFormFieldInfo = styled.div(({ status, theme: { base: { 'font-size': fontSize, 'font-scale': fontScale, spacing, palette }, components: { 'form-field': formField } } }) => {
    const { xxs: infoFontSize } = calculateFontSize(fontSize, fontScale);
    return css `
      max-width: max-content;
      font-size: ${infoFontSize};
      word-break: break-word;

      &:not(:empty) {
        margin-block-start: calc(0.25 * ${spacing});
      }

      ${status &&
        formField[status] &&
        css `
        color: ${tryCatch(() => readableHue(formField[status]['status-color'], palette['primary-background']), () => formField[status]['status-color'])};
      `}
    `;
});
StyledFormFieldInfo.defaultProps = defaultThemeProp;
export const StyledLabelRow = styled.div ``;
export const StyledFormField = styled.div(props => {
    const { asFieldset, showAdditionalInfo, disabled, required, theme: { base: { palette: { urgent }, 'disabled-opacity': disabledOpacity, spacing, 'hit-area': { 'compact-min': hitAreaCompact } } } } = props;
    return css `
    ${disabled &&
        css `
      opacity: ${disabledOpacity};
      -webkit-user-select: none;
      user-select: none;
    `}
    position: relative;
    border: 0;

    &:has(${StyledRadioCheckInput}:only-of-type) {
      ${StyledFormFieldInfo} {
        min-width: 100%;
      }
    }

    ${StyledFlex}:has(${StyledRadioCheck}) {
      flex-shrink: 0;
    }

    > ${StyledLabel}, > ${StyledLabelRow}, > ${StyledFlex}:has(> ${StyledLabel}) {
      &:not(:empty) {
        margin-bottom: calc(0.25 * ${spacing});
        min-height: ${hitAreaCompact};
      }
    }

    > ${StyledLabel}, > ${StyledLabelRow} > ${StyledLabel}, > ${StyledFlex} > ${StyledLabel} {
      ${required &&
        css `
        &::after {
          content: ${'"\\00a0*" / ""'};
          color: ${urgent};
        }
      `}

      ${disabled &&
        css `
        cursor: not-allowed;
      `}
    }

    ${asFieldset &&
        showAdditionalInfo &&
        css `
      > ${StyledFlex} > ${StyledLabel} {
        display: block;
      }

      > ${StyledFlex}:has(> ${StyledLabel}) > ${StyledAdditionalInfo} {
        align-self: flex-start;
      }
    `}
  `;
});
StyledFormField.defaultProps = defaultThemeProp;
const StyledSuggestionButton = styled(Button)(({ theme: { base: { 'font-size': fontSize, 'font-scale': fontScale, 'border-radius': baseRadius, spacing, palette }, components: { 'form-control': { 'border-radius': radius, 'border-width': borderWidth }, 'form-field': formField } } }) => {
    const { xxs: buttonFontSize } = calculateFontSize(fontSize, fontScale);
    const backgroundColor = tryCatch(() => readableHue(formField.pending['status-color'], palette['primary-background']), () => formField.pending['status-color']);
    const hoverColors = getHoverColors(backgroundColor);
    const color = tryCatch(() => readableColor(backgroundColor));
    const borderColor = color ? rgba(color, 0.4) : color;
    return css `
    background-color: ${backgroundColor};
    color: ${color};
    font-size: ${buttonFontSize};
    min-width: calc(3 * ${spacing});
    min-height: calc(3 * ${spacing});
    padding: 0 ${spacing};
    border-radius: 0;
    border: none;

    &:first-child {
      border-inline-end: ${borderWidth} solid ${borderColor};
      border-end-start-radius: calc(${baseRadius} * ${radius});
      margin-inline-start: calc(2 * ${spacing});
    }

    &:last-child {
      border-end-end-radius: calc(${baseRadius} * ${radius});
      margin-inline-start: 0;
    }

    &:hover {
      color: ${hoverColors.foreground};
      background-color: ${hoverColors.background};
    }

    @media (pointer: coarse) {
      min-height: 2rem;
    }
  `;
});
StyledSuggestionButton.defaultProps = defaultThemeProp;
const statusIconMap = { error: 'warn-solid', warning: 'diamond-minus', success: 'check' };
const FormField = forwardRef(function FormField(props, ref) {
    const uid = useUID();
    const { testId, children: controlElement, id = uid, as = 'div', label, labelAs: labelAsProp = 'label', labelFor = id, labelId: labelIdProp, labelHidden = false, labelAfter = false, info, status, suppressAnnouncements, isRadioCheck, charLimitDisplay, required = false, disabled = false, readOnly = false, inline = false, onClear, actions, container, additionalInfo, onResolveSuggestion, 'aria-describedby': ariaDescribedBy, className, ...restProps } = props;
    const testIds = useTestIds(testId, getFormFieldTestIds);
    const asFieldset = as === 'fieldset' || (typeof as !== 'string' && 'target' in as && as.target === 'fieldset');
    const t = useI18n();
    const { announceAssertive } = useLiveLog();
    const labelAs = asFieldset || labelAsProp === 'legend' ? 'span' : labelAsProp;
    const hasSuggestion = status === 'pending' && !!onResolveSuggestion;
    const consolidatedRef = useConsolidatedRef(ref);
    const labelRef = useRef(null);
    const [labelText, setLabelText] = useState(null);
    const showAdditionalInfo = !!additionalInfo && !disabled && !labelHidden;
    const labelId = asFieldset && !labelIdProp ? `${id}-label` : labelIdProp;
    const labelContent = (_jsxs(_Fragment, { children: [_jsx(Label, { "data-testid": testIds.label, id: labelId, as: labelAs, htmlFor: labelAs === 'label' ? labelFor : undefined, labelHidden: labelHidden, onClick: (e) => {
                    if (readOnly)
                        e.preventDefault();
                }, inline: inline, ref: labelRef, children: label }), showAdditionalInfo && labelText && (_jsx(AdditionalInfo, { "data-testid": testIds.additionalInfo, heading: additionalInfo.heading, contextualLabel: labelText, children: additionalInfo.content }))] }));
    let labelRow;
    if (!isRadioCheck && !asFieldset && !labelHidden) {
        labelRow = (_jsx(Flex, { as: StyledLabelRow, container: { justify: 'between', alignItems: 'end' }, item: { alignSelf: 'stretch' }, children: labelContent }));
    }
    else if (asFieldset && !labelHidden) {
        labelRow = (_jsx(Flex, { container: {
                alignItems: 'end',
                justify: showAdditionalInfo && !isRadioCheck ? 'between' : undefined
            }, children: labelContent }));
    }
    else {
        labelRow = labelContent;
    }
    useEffect(() => {
        setLabelText(labelRef.current?.textContent ?? null);
    }, [label]);
    useEffect(() => {
        if (suppressAnnouncements || (status !== 'error' && status !== 'warning'))
            return;
        let message = t(status);
        if (typeof info === 'string')
            message = `${message} ${info}`;
        if (labelRef.current?.textContent)
            message = `${labelRef.current?.textContent} ${message}`;
        announceAssertive({ message, type: status });
    }, [status, info]);
    // fieldset or single form control element
    let content;
    if (asFieldset || Children.count(controlElement) > 1) {
        content = controlElement;
    }
    else {
        const controlElementAriaDescribedBy = Children.only(controlElement).props['aria-describedby'];
        content = cloneElement(controlElement, {
            'aria-describedby': [controlElementAriaDescribedBy, info && !readOnly ? `${id}-info` : undefined]
                .join(' ')
                .trim() || undefined
        });
    }
    if (actions) {
        content = (_jsxs(Flex, { container: { alignItems: 'center', gap: 0.5 }, children: [content, _jsx(Actions, { items: actions, menuAt: 3 })] }));
    }
    let infoContent = (_jsxs(Flex, { id: `${id}-info`, "data-testid": testIds.info, status: status, as: StyledFormFieldInfo, container: { alignItems: 'center', gap: 0.5 }, children: [status && status !== 'pending' && (_jsxs(_Fragment, { children: [_jsx(Flex, { item: { alignSelf: 'start' }, as: StyledStatusIcon, status: status, name: statusIconMap[status] }), _jsx(VisuallyHiddenText, { children: `${t(status)} ` })] })), info] }));
    if (charLimitDisplay) {
        infoContent = (_jsxs(Flex, { container: { justify: infoContent ? 'between' : 'end', gap: 1 }, children: [infoContent, _jsx(Flex, { item: { shrink: 0 }, children: charLimitDisplay })] }));
    }
    if (hasSuggestion) {
        const focusables = getFocusables(consolidatedRef);
        infoContent = (_jsxs(Flex, { container: { alignItems: 'start', justify: 'between' }, children: [_jsxs(StyledFormFieldInfo, { "data-testid": testIds.info, status: status, id: `${id}-info`, children: [t('suggestion_info'), _jsx(VisuallyHiddenText, { "aria-live": 'polite', children: t('suggestion_assist') })] }), _jsxs(Flex, { container: { wrap: 'nowrap' }, children: [_jsx(StyledSuggestionButton, { "data-testid": testIds.suggestionReject, onClick: () => {
                                onResolveSuggestion(false);
                                focusables[0]?.focus();
                            }, "aria-label": `${t('no')}, ${t('reject_suggestion_button_a11y')}${labelText ? ` - ${labelText}` : ''}`, children: t('no') }), _jsx(StyledSuggestionButton, { "data-testid": testIds.suggestionAccept, onClick: () => {
                                onResolveSuggestion(true);
                                focusables[0]?.focus();
                            }, "aria-label": `${t('yes')}, ${t('accept_suggestion_button_a11y')}${labelText ? ` - ${labelText}` : ''}`, children: t('yes') })] })] }));
    }
    const onKeyDown = (e) => {
        if (e.key === 'Enter') {
            const target = e.target;
            if (!target.closest('button')) {
                e.preventDefault();
                onResolveSuggestion?.(true);
            }
        }
    };
    const descriptionIds = [];
    if (ariaDescribedBy)
        descriptionIds.push(ariaDescribedBy);
    if (asFieldset && info)
        descriptionIds.push(`${id}-info`);
    return (_jsxs(Flex, { "data-testid": testIds.root, ...restProps, container: {
            direction: inline ? 'row' : 'column',
            alignItems: inline ? 'center' : undefined,
            wrap: isRadioCheck ? 'wrap' : undefined,
            ...container
        }, as: StyledFormField, asFieldset: asFieldset, isRadioCheck: isRadioCheck, showAdditionalInfo: showAdditionalInfo, id: `${id}-field`, forwardedAs: as, required: required, disabled: disabled, readOnly: readOnly, onKeyDown: hasSuggestion ? onKeyDown : undefined, "aria-describedby": descriptionIds.length ? descriptionIds.join(' ') : undefined, "aria-labelledby": asFieldset ? labelId : undefined, ref: consolidatedRef, className: createClassName('form-field', className, { status }), children: [(asFieldset || !labelAfter) && labelRow, content, !asFieldset && labelAfter && labelRow, !readOnly && infoContent, isRadioCheck && onClear && (_jsx(StyledClearButton, { variant: 'link', onClick: () => {
                    onClear();
                }, children: t('clear_selection') }))] }));
});
export default withTestIds(FormField, getFormFieldTestIds);
//# sourceMappingURL=FormField.js.map