import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { forwardRef, useEffect, useRef, useState, useMemo, useLayoutEffect, useCallback, cloneElement } from 'react';
import { getActiveElement, withTestIds, isValidElement, hasProp } from '../../utils';
import Icon, { registerIcon } from '../Icon';
import { useConsolidatedRef, useElement, useEscape, useFocusTrap, useFocusWithin, useI18n, usePrevious, useTestIds, useUID } from '../../hooks';
import Grid from '../Grid';
import Flex from '../Flex';
import FieldValueList from '../FieldValueList';
import { StyledImage } from '../Image';
import * as pictureIcon from '../Icon/icons/picture.icon';
import ShowMoreLess from '../ShowMoreLess';
import Tooltip from '../Tooltip';
import { getSelectionCardTestIds } from './SelectionCard.test-ids';
import { StyledSelectionCard, StyledContentContainer, StyledImageContainer, StyledSelectionCardInline, StyledSelectionCardStacked, StyledValueList, StyledHeader, StyledImageCell, StyledContentCell, StyledTileContent, StyledCardFooter, StyledSingleField } from './SelectionCard.styles';
import SelectionCardActions from './SelectionCardActions';
registerIcon(pictureIcon);
const isTileContent = (img) => {
    return 'foregroundColor' in img;
};
export const focusableSelector = 'a[href], button, input, textarea, select, details, video[controls], audio[controls]';
const SingleField = ({ id, 'data-testid': testId, truncate, value }) => {
    const [el, setEl] = useElement(null);
    return (_jsxs(_Fragment, { children: [_jsx(StyledSingleField, { ref: setEl, id: id, "data-testid": testId, truncate: truncate, children: value }), truncate && el && (_jsx(Tooltip, { target: el, smart: true, children: value }))] }));
};
const useContentHeight = (contentRef, targetRef) => {
    useLayoutEffect(() => {
        if (!contentRef.current || !targetRef.current)
            return;
        const resizeObserver = new ResizeObserver(() => {
            requestAnimationFrame(() => {
                targetRef.current?.style.setProperty('--content-height', `${contentRef.current?.scrollHeight}px`);
            });
        });
        resizeObserver.observe(contentRef.current);
        return () => {
            resizeObserver.disconnect();
        };
    }, []);
};
const SelectionCard = forwardRef(function SelectionCard(props, ref) {
    const uid = useUID();
    const { testId, id = uid, 'aria-label': label, heading, disabled = false, readOnly, image, footer, fields = [], onClick, onKeyDown, actions, additionalInfo, ...restProps } = props;
    const t = useI18n();
    const contentRef = useRef(null);
    const containerRef = useConsolidatedRef(ref);
    const [focusOnInput, setFocusOnInput] = useState(false);
    const [hasInteractiveElements, setHasInteractiveElements] = useState(0);
    const [isBrokenImage, setIsBrokenImage] = useState(false);
    const isTile = image !== undefined && isTileContent(image);
    const tile = isTile ? image : undefined;
    const resolvedImageSrc = !isTile ? image?.src : undefined;
    const prevImageSrc = usePrevious(resolvedImageSrc);
    const testIds = useTestIds(testId, getSelectionCardTestIds);
    const contentId = `${id}-content`;
    const hasAdditionalContent = fields.length > 0;
    useEffect(() => {
        const focusables = containerRef.current?.querySelectorAll(focusableSelector);
        setHasInteractiveElements(focusables?.length || 0);
        setFocusOnInput(focusables?.length === 1 && focusables?.[0] instanceof HTMLInputElement);
        focusables?.forEach(el => el.hasAttribute('data-main-focus')
            ? el.removeAttribute('tabindex')
            : el.setAttribute('tabindex', '-1'));
    }, [additionalInfo, fields, actions]);
    useFocusTrap(focusOnInput ? null : contentRef, false, [contentRef]);
    useFocusWithin([focusOnInput ? null : contentRef], focused => contentRef.current
        ?.querySelectorAll(focusableSelector)
        .forEach(el => (focused ? el.removeAttribute('tabindex') : el.setAttribute('tabindex', '-1'))));
    useEscape(() => containerRef.current?.focus(), focusOnInput ? null : containerRef, [
        containerRef
    ]);
    useContentHeight(contentRef, containerRef);
    const handleKeyDown = useCallback((event) => {
        if (event.key === 'Enter' &&
            containerRef.current === getActiveElement() &&
            (!focusOnInput || (focusOnInput && hasInteractiveElements > 1))) {
            event.preventDefault();
            contentRef.current?.querySelectorAll(focusableSelector)[0]?.focus();
        }
        onKeyDown?.(event);
    }, [containerRef, contentRef]);
    const imageContent = useMemo(() => {
        if (!image)
            return undefined;
        const innerContent = tile ? (_jsx(StyledTileContent, { "data-tile-content": true, foregroundColor: tile.foregroundColor, backgroundColor: tile.backgroundColor, size: tile.size, children: tile.icon ? _jsx(Icon, { name: tile.icon }) : tile.text || _jsx(Icon, { name: 'picture' }) })) : (_jsx(Flex, { container: { justify: 'center', alignItems: 'center' }, as: StyledImageContainer, placement: image.placement, size: image.size, children: (isBrokenImage && resolvedImageSrc === prevImageSrc) || resolvedImageSrc === undefined ? (_jsx(Icon, { name: 'picture', "aria-label": t('image_load_error') })) : (_jsx(StyledImage, { "data-testid": testIds.image, ...image, onError: () => setIsBrokenImage(true), onLoad: () => setIsBrokenImage(false) })) }));
        return (_jsx(Flex, { container: { justify: 'center', alignItems: 'center' }, as: StyledImageCell, placement: image.placement, size: image.size, isTile: isTile, style: !isTile && image.src && !isBrokenImage ? { '--bg-image': `url(${image.src})` } : undefined, children: innerContent }));
    }, [
        isBrokenImage,
        prevImageSrc,
        image?.placement,
        image?.size,
        tile?.icon,
        tile?.text,
        tile?.foregroundColor,
        tile?.backgroundColor
    ]);
    let asProp = StyledSelectionCard;
    if (image) {
        asProp = (image.placement ?? 'inline-start').startsWith('block')
            ? StyledSelectionCardStacked
            : StyledSelectionCardInline;
    }
    const isFieldValueListItemProps = (item) => {
        return hasProp(item, 'name');
    };
    return (_jsxs(Grid, { "data-testid": testIds.root, ...restProps, id: id, onClick: onClick, as: asProp, placement: image?.placement, size: image?.size, container: { cols: '1fr', rows: 'auto' }, disabled: disabled, readOnly: readOnly, role: hasInteractiveElements ? 'group' : 'article', "aria-label": label, ref: containerRef, "data-main-focus": focusOnInput ? undefined : true, tabIndex: focusOnInput ? undefined : 0, onKeyDown: handleKeyDown, children: [image && image.placement !== 'inline-end' && imageContent, _jsxs(StyledContentCell, { children: [_jsxs(Flex, { as: StyledContentContainer, container: { direction: 'column', gap: 0.75 }, ref: contentRef, children: [_jsxs(Flex, { as: StyledHeader, container: { alignItems: 'center', justify: 'between' }, children: [isValidElement(heading) ? (cloneElement(heading, {
                                        ...{
                                            tabIndex: focusOnInput ? undefined : -1,
                                            additionalInfo,
                                            'data-main-focus': focusOnInput ? true : undefined,
                                            'aria-details': hasAdditionalContent ? contentId : undefined
                                        }
                                    })) : (_jsx("span", { "data-testid": testIds.label, "aria-details": hasAdditionalContent ? contentId : undefined, children: heading })), actions && (_jsx(SelectionCardActions, { "data-testid": testIds.actions, actions: actions, disabled: disabled, contextualLabel: label }))] }), hasAdditionalContent &&
                                (fields.every(field => isFieldValueListItemProps(field)) ? (_jsx(FieldValueList, { id: contentId, "data-testid": testIds.content, fields: fields })) : (_jsx(_Fragment, { children: fields.length === 1 ? (_jsx(SingleField, { id: contentId, "data-testid": testIds.content, truncate: fields[0].truncate, value: fields[0].value })) : (_jsx(Flex, { container: { direction: 'column', gap: 1 }, as: StyledValueList, id: contentId, "data-testid": testIds.content, children: fields.map(field => (_jsx("li", { children: field.truncate ? (_jsx(ShowMoreLess, { lines: 3, children: field.value })) : (field.value) }, field.id))) })) })))] }), footer && _jsx(StyledCardFooter, { children: footer })] }), image?.placement === 'inline-end' && imageContent] }));
});
export default withTestIds(SelectionCard, getSelectionCardTestIds);
//# sourceMappingURL=SelectionCard.js.map