import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import classNames from 'classnames';
import './MultiSelect.scss';
import Dropdown from './Dropdown';
import Icon from '../Icon';
import Typography from '../Typography';
import Tooltip from '../Tooltip';
import { checkEmpty } from '../../utils/checkEmpty/checkEmpty';
import { isTextTruncated, truncateText, } from '../../utils/truncateText/truncateText';
import { getLabel, getValue, } from '../../utils/getSelectOptionValue/getSelectOptionValue';
import { useMergeRefs } from '../../hooks/useMergeRefs';
import { ALPHA_NUM_EXTENDED_REGEX } from '../../validations/regex';
const MAX_SEARCH_CHARACTER_LENGTH = 100;
const FONT_SIZE = 7.5;
const ChipElement = ({ label, onChipCloseClick, disableChip, zIndex, maxChipWidth, closeIconTooltip, }) => {
    if (label) {
        return (_jsxs("div", { className: "ff-multiselect-chip", children: [_jsx("span", { className: `ff-multiselect-chip-label ${disableChip && 'label-padding'}`, children: _jsx(Tooltip, { style: { display: 'flex', cursor: 'default' }, placement: "bottom", title: isTextTruncated(label, maxChipWidth, 'pixel') ? label : '', zIndex: zIndex + 1, children: _jsx(Typography, { fontSize: 10, lineHeight: '14px', as: "span", children: typeof label === 'string'
                                ? truncateText(label, maxChipWidth, 'pixel')
                                : label }) }) }), _jsx(Tooltip, { title: closeIconTooltip && !disableChip ? 'Remove' : '', children: _jsx(Icon, { name: "close_pill", height: 12, width: 12, disabled: disableChip, cursorType: "pointer", className: !disableChip ? 'ff-multiselect-chip-close-icon' : '', onClick: !disableChip ? onChipCloseClick : () => { } }) })] }));
    }
    return null;
};
const MultiSelect = ({ options = [], type = 'text', selectedOptions = [], onChange = () => { }, acceptNewOption = false, zIndex = 100, label = '', onSearch = () => { }, required = false, disabled = false, errorMessage = 'Fill this field', displayCount: initialDisplayCount = false, isAllSelected, onToggleAllSelect, 
// New prop added
displayAllSelectedAsText, isAllSelect, placeholderForSearching = 'Search', variant = 'default', onLabelPlusIconClick = async () => { }, className = '', onSelectButtonClick = () => { }, labelAccessor = 'label', valueAccessor = 'value', searchAccessor = valueAccessor, withSelectButton = variant === 'machines' ? true : false, loadMoreOptions = () => { }, onEnter = () => false, maxVisibleChips = 1, onBlur = () => { }, maxDropdownHeight = 162, dropdownContainerRef, noResultsMessage, chipAccessor = labelAccessor, isCloseIconToolTip = false, }) => {
    const [isOpen, setIsOpen] = useState(false);
    const [allOptions, setAllOptions] = useState(options);
    const [searchedKeyword, setSearchedKeyword] = useState('');
    const [isSelectFocusedOnce, setIsSelectFocusedOnce] = useState(false);
    const [inputError, setInputError] = useState('');
    const [displayIcon, setDisplayIcon] = useState(false);
    const [displayCount] = useState(initialDisplayCount);
    const [dropdownPosition, setDropdownPosition] = useState({
        top: 0,
        left: 0,
        width: 0,
        fromBottom: 0,
        selectHeight: 0,
    });
    const [labelBgColor, setLabelBgColor] = useState('white');
    const inputRef = useRef(null);
    const dropdownWrapper = useRef(null);
    const dropdownRef = useRef(null);
    const selectWrapper = useRef(null);
    const mergedRef = useMergeRefs(dropdownRef, dropdownContainerRef);
    let isFieldSkipped = isSelectFocusedOnce && selectedOptions?.length === 0;
    const [visibleCount, setVisibleCount] = useState(maxVisibleChips ?? 0);
    useLayoutEffect(() => {
        if (selectWrapper.current && selectedOptions) {
            const containerWidth = selectWrapper.current.getBoundingClientRect().width;
            let totalWidthUsed = 0;
            let count = 0;
            selectedOptions.forEach((option) => {
                const label = option[labelAccessor];
                const characterCount = Math.min(label?.length || 0, Math.floor(containerWidth / FONT_SIZE)) || 0;
                const currentElementChipWidth = characterCount * FONT_SIZE + 25;
                if (totalWidthUsed + currentElementChipWidth <= containerWidth - 60) {
                    count++;
                }
                totalWidthUsed += currentElementChipWidth;
            });
            setVisibleCount(Math.max(count, 1));
        }
    }, [selectedOptions, dropdownPosition, selectWrapper.current]);
    const hiddenCount = selectedOptions?.length - visibleCount;
    const handleClick = () => {
        if (!isOpen) {
            setIsOpen(true);
        }
        else if (withSelectButton && dropdownRef.current) {
            setIsOpen(false);
        }
    };
    const toggleDropdown = (e) => {
        e.stopPropagation();
        inputRef.current?.focus();
        setIsOpen((prev) => !prev);
        if (!isSelectFocusedOnce && isOpen) {
            setIsSelectFocusedOnce(true);
        }
    };
    const handleOptionChange = (selectedOption, isChecked) => {
        if (selectedOption?.isDisabled) {
            return;
        }
        inputRef.current?.focus();
        const updatedOptions = allOptions.map((option) => getValue(option, valueAccessor) ===
            getValue(selectedOption, valueAccessor)
            ? { ...option, isChecked, sort: Date.now() }
            : option);
        setAllOptions(updatedOptions);
        const tempCheckedOptions = updatedOptions
            .filter((option) => option.isChecked)
            .sort((a, b) => a.sort - b.sort)
            .map(({ isChecked, ...rest }) => rest);
        if (!isSelectFocusedOnce) {
            setIsSelectFocusedOnce(true);
        }
        if (checkEmpty(selectedOption)) {
            setIsOpen(false);
            onSelectButtonClick?.(tempCheckedOptions);
            return;
        }
        onChange && onChange(tempCheckedOptions);
        setSearchedKeyword('');
    };
    const handleChipCloseClick = (option, e) => {
        e.stopPropagation();
        handleOptionChange(option, false);
    };
    const handleChipCloseAll = (e) => {
        e.stopPropagation();
        const updatedOptions = allOptions.map((option) => ({
            ...option,
            isChecked: false,
        }));
        setAllOptions(updatedOptions);
        onChange && onChange([]);
    };
    const handleKeyEnter = (e) => {
        if (acceptNewOption && e.key === 'Enter') {
            setInputError('');
            if (type === 'email') {
                const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
                if (!emailPattern.test(searchedKeyword)) {
                    setIsOpen(false);
                    setInputError('Recipient Email is not valid.');
                    return;
                }
            }
            const isDropdownOpen = onEnter?.(searchedKeyword);
            if (isDropdownOpen) {
                setIsOpen(true);
            }
            else {
                setSearchedKeyword('');
                setIsOpen(false);
            }
        }
    };
    const handleIconClick = async () => {
        try {
            await onLabelPlusIconClick(searchedKeyword);
            // Empty the input field & remove the icon after adding the label successfully
            setSearchedKeyword('');
            setDisplayIcon(false);
        }
        catch (error) { }
    };
    useEffect(() => {
        const getActualBackgroundColor = (element) => {
            let currentElement = element;
            while (currentElement) {
                const styles = window.getComputedStyle(currentElement);
                if (styles.backgroundColor !== 'rgba(0, 0, 0, 0)') {
                    return styles.backgroundColor;
                }
                currentElement = currentElement.parentElement;
            }
            return '';
        };
        if (selectWrapper.current) {
            const parentElement = selectWrapper.current.parentElement?.parentElement;
            if (parentElement) {
                const bgColor = getActualBackgroundColor(parentElement);
                if (bgColor) {
                    setLabelBgColor(bgColor);
                }
            }
        }
    }, [selectWrapper.current]);
    const getScrollableParent = (element) => {
        if (!element)
            return null;
        let parent = element.parentElement;
        while (parent) {
            const { overflowY, overflowX } = window.getComputedStyle(parent);
            if (/(auto|scroll|overlay)/.test(overflowY) ||
                (/(auto|scroll|overlay)/.test(overflowX) &&
                    parent.scrollWidth > parent.clientWidth)) {
                return parent;
            }
            parent = parent.parentElement;
        }
        return document.documentElement;
    };
    useEffect(() => {
        calculatePosition();
    }, [searchedKeyword]);
    useEffect(() => {
        if (!selectWrapper.current)
            return;
        const scrollableParent = getScrollableParent(selectWrapper.current);
        // Attach scroll event to detected parent or window
        scrollableParent?.addEventListener('scroll', () => {
            setIsOpen(false);
        }, {
            passive: true,
        });
        return () => {
            scrollableParent?.removeEventListener('scroll', () => {
                setIsOpen(false);
            });
        };
    }, []);
    const calculatePosition = () => {
        if (dropdownWrapper.current && selectWrapper.current) {
            const rect = dropdownWrapper.current.getBoundingClientRect();
            const rect2 = selectWrapper.current.getBoundingClientRect();
            setDropdownPosition({
                top: rect.bottom + window.scrollY,
                left: rect.left + window.scrollX,
                width: rect.width,
                fromBottom: document.documentElement.clientHeight - (rect.bottom - 4),
                selectHeight: rect2.height,
            });
        }
    };
    const handleSearch = (e) => {
        if (!isOpen) {
            setIsOpen(true);
        }
        const input = e.target.value;
        setSearchedKeyword(input);
        onSearch?.(input);
        if (input?.length > 2 && input === input.trim()) {
            const matchedOption = allOptions.find((option) => getLabel(option, searchAccessor)?.toLowerCase() ===
                input.toLowerCase());
            setDisplayIcon(!matchedOption);
        }
        else {
            setDisplayIcon(false);
        }
    };
    const handleHiddenChips = () => {
        setIsOpen(false);
    };
    useEffect(() => {
        const rect = dropdownWrapper.current?.getBoundingClientRect();
        setDropdownPosition((prev) => ({ ...prev, width: rect?.width }));
    }, [displayIcon]);
    useEffect(() => {
        if (isOpen) {
            calculatePosition();
        }
    }, [isOpen, allOptions]);
    function getScrollbarWidth() {
        const div = document.createElement('div');
        div.style.visibility = 'hidden';
        div.style.overflow = 'scroll';
        document.body.appendChild(div);
        const scrollbarWidth = div.offsetWidth - div.clientWidth;
        document.body.removeChild(div);
        return scrollbarWidth;
    }
    const onSelectToggleScroll = (isEnabled) => {
        const bodyScrollWidth = getScrollbarWidth();
        if (document.body.scrollHeight > window.innerHeight) {
            document.body.style.paddingRight = isEnabled
                ? ''
                : `${bodyScrollWidth}px`;
        }
        document.body.style.overflow = isEnabled ? '' : 'hidden';
    };
    useEffect(() => {
        if (isOpen) {
            onSelectToggleScroll(!isOpen);
        }
        if (dropdownRef?.current) {
            inputRef?.current?.focus();
        }
        return () => {
            onSelectToggleScroll(true);
        };
    }, [isOpen]);
    useEffect(() => {
        if (!isOpen && isSelectFocusedOnce) {
            onBlur();
        }
    }, [isOpen, isSelectFocusedOnce]);
    useEffect(() => {
        if (!checkEmpty(options)) {
            let initializeOptions = options;
            if (!checkEmpty(selectedOptions)) {
                initializeOptions = options.map((option) => {
                    const selectedIndex = selectedOptions.findIndex((selectedOption) => getValue(selectedOption, valueAccessor) ===
                        getValue(option, valueAccessor));
                    return {
                        ...option,
                        isChecked: selectedIndex !== -1,
                        ...(selectedIndex !== -1 && { sort: selectedIndex }),
                    };
                });
            }
            setAllOptions(initializeOptions);
        }
    }, [options, selectedOptions]);
    useEffect(() => {
        const handleClickAnywhere = (event) => {
            if (withSelectButton &&
                dropdownWrapper.current &&
                selectWrapper.current &&
                dropdownRef.current &&
                !dropdownRef.current.contains(event?.target) &&
                !selectWrapper.current.contains(event?.target)) {
                setInputError('');
                setIsOpen(false);
                setSearchedKeyword('');
                if (!isSelectFocusedOnce) {
                    setIsSelectFocusedOnce(true);
                }
            }
            if (dropdownWrapper.current &&
                inputRef.current &&
                selectWrapper.current &&
                dropdownRef.current &&
                !inputRef.current.contains(event?.target) &&
                !dropdownRef.current.contains(event?.target) &&
                !selectWrapper.current.contains(event?.target) &&
                !(event?.target &&
                    event.target.closest('.ff-label-plus-icon'))) {
                setInputError('');
                setIsOpen(false);
                if (!isSelectFocusedOnce) {
                    setIsSelectFocusedOnce(true);
                }
            }
        };
        window.addEventListener('resize', calculatePosition);
        window.addEventListener('click', handleClickAnywhere, true);
        return () => {
            window.removeEventListener('resize', calculatePosition);
            window.removeEventListener('click', handleClickAnywhere);
            document.body.style.overflow = 'auto';
        };
    }, []);
    const hideSearchField = displayAllSelectedAsText && selectedOptions?.length === allOptions?.length;
    const isAllSelectedData = selectedOptions?.length === allOptions?.length;
    return (_jsxs("div", { className: `ff-multiselect-container-with-icon ${className}`, children: [_jsxs("div", { ref: selectWrapper, className: classNames('ff-multiselect-wrapper', {
                    'ff-multiselect-wrapper--with-options': selectedOptions?.length,
                    'ff-multiselect-wrapper--opened-dropdown': isOpen,
                    'ff-multiselect-wrapper--error': (isFieldSkipped && required) || inputError,
                    'ff-multiselect-wrapper--disabled': disabled,
                }), children: [_jsxs("div", { className: "ff-multiselect", onClick: handleClick, children: [_jsxs("div", { className: "ff-multiselect__main", children: [_jsx(Typography, { style: { backgroundColor: labelBgColor }, className: classNames({
                                            'active-default-label': isOpen ||
                                                (!withSelectButton && selectedOptions?.length) ||
                                                (isFieldSkipped && required),
                                            'default-label': !isOpen && !selectedOptions?.length,
                                        }), required: required, children: label }), _jsxs("div", { className: classNames('ff-multiselect-chip-container', {
                                            ['ff-multiselect-chip-container__all_label']: isAllSelectedData,
                                        }), children: [!withSelectButton &&
                                                (displayAllSelectedAsText &&
                                                    selectedOptions?.length === allOptions?.length &&
                                                    !checkEmpty(allOptions) &&
                                                    labelAccessor !== 'name' ? (_jsx(ChipElement, { zIndex: zIndex, label: "All", onChipCloseClick: handleChipCloseAll, disableChip: false, maxChipWidth: dropdownPosition.width - 85 }, "all")) : displayCount ? (_jsx(_Fragment, { children: selectedOptions.slice(0, visibleCount).map((option) => (_jsx(ChipElement, { zIndex: zIndex, label: getLabel(option, chipAccessor) || '', onChipCloseClick: (e) => handleChipCloseClick(option, e), disableChip: option?.isDisabled || false, maxChipWidth: dropdownPosition.width - 85, closeIconTooltip: isCloseIconToolTip }, getLabel(option, labelAccessor)))) })) : (selectedOptions.map((option) => (_jsx(ChipElement, { zIndex: zIndex, label: getLabel(option, chipAccessor) || '', onChipCloseClick: (e) => handleChipCloseClick(option, e), disableChip: option?.isDisabled || false, maxChipWidth: dropdownPosition.width - 85 }, getLabel(option, labelAccessor)))))), !hideSearchField && (_jsx("div", { className: "ff-multiselect-input-container", children: _jsx("input", { value: searchedKeyword, type: type, autoComplete: "off", placeholder: placeholderForSearching, ref: inputRef, onChange: handleSearch, onKeyDown: handleKeyEnter, id: "input-ele", className: "ff-select-input", style: {
                                                        display: isOpen || (selectedOptions?.length && !withSelectButton)
                                                            ? 'inherit'
                                                            : 'none',
                                                    } }) }))] })] }), hiddenCount > 0 && displayCount && (_jsx("div", { className: "ff-multiselect-more-chip", onClick: handleHiddenChips, children: _jsxs(Typography, { fontSize: 12, fontWeight: "semi-bold", lineHeight: "16px", color: "var(--brand-color)", children: ["+", hiddenCount] }) })), _jsx("div", { onClick: (e) => {
                                    toggleDropdown(e);
                                }, className: "ff-multiselect__toggle", children: _jsx(Icon, { name: "arrow_down", className: classNames({
                                        'ff-select-arrow--opened-dropdown': isOpen,
                                        'ff-select-arrow': !isOpen,
                                    }), color: isOpen ? 'var(--brand-color)' : 'var(--default-icon-color)', height: 8, width: 12 }) })] }), _jsxs("div", { ref: dropdownWrapper, children: [(inputError || (isFieldSkipped && required && errorMessage)) && (_jsx(Typography, { children: inputError || errorMessage, fontSize: 10, className: "error-text" })), isOpen &&
                                createPortal(_jsx(Dropdown, { ref: mergedRef, searchedKeyword: searchedKeyword, checkedOptions: selectedOptions, handleOptionChange: handleOptionChange, options: allOptions, dropdownPosition: dropdownPosition, zIndex: zIndex, withSelectButton: withSelectButton, labelAccessor: labelAccessor, valueAccessor: valueAccessor, searchAccessor: searchAccessor, loadMoreOptions: loadMoreOptions, isAllSelected: isAllSelected, onToggleAllSelect: onToggleAllSelect, isAllSelect: isAllSelect, maxDropdownHeight: maxDropdownHeight, variant: variant, handleIconClick: handleIconClick, noResultsMessage: noResultsMessage, maxSearchCharacterLength: MAX_SEARCH_CHARACTER_LENGTH }), document.body)] })] }), variant === 'labels' && displayIcon && (_jsx(Tooltip, { title: "Add Label", placement: "top", zIndex: zIndex + 1, children: _jsx(Icon, { name: 'label_plus', onClick: handleIconClick, className: "ff-label-plus-icon", disabled: MAX_SEARCH_CHARACTER_LENGTH <= (searchedKeyword?.length || 0) ||
                        !ALPHA_NUM_EXTENDED_REGEX.test(searchedKeyword) }) }))] }));
};
export default MultiSelect;
//# sourceMappingURL=MultiSelect.js.map