import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useRef, useContext, useEffect, useCallback } from 'react';
import './MenuOption.scss';
import Icon from '../Icon';
import classNames from 'classnames';
import Tooltip from '../Tooltip';
import Typography from '../Typography';
import { createPortal } from 'react-dom';
import { ThemeContext } from '../ThemeProvider/ThemeProvider';
import useClickOutside from '../../hooks/useClickOutside';
import { getAnchorElement } from '../../utils/getAnchorElement/getAnchorElement';
import { checkEmpty } from '../../utils/checkEmpty/checkEmpty';
const Option = ({ option, onClick, alignOption }) => (_jsxs("div", { className: classNames('ff-options', {
        'ff-disable-option': option.disable,
        'align-center': alignOption === 'center',
        'align-right': alignOption === 'right',
        'align-left': alignOption === 'left',
    }), onClick: () => !option.disable && onClick(option), children: [typeof option.icon === 'string' ? (_jsx(Icon, { name: option.icon, color: option.iconColor, height: 16, width: 16 })) : option.icon, _jsx(Typography, { as: "label", lineHeight: "18px", color: option.icon === 'delete' ? 'var(--delete-text-color)' : '', children: option.label })] }));
const calculatePosition = (menuPosition, dropdownPlacement, optionCardHeight, optionCardWidth, isAddResourceButton) => {
    const { top, left, height, width } = menuPosition;
    const availableSpace = {
        top,
        bottom: window.innerHeight - (top + height),
        left,
        right: window.innerWidth - (left + width),
    };
    const gap = 2;
    const minGap = 8;
    const actualOptionWidth = optionCardWidth || width;
    let newTop = top;
    let newLeft = left;
    switch (dropdownPlacement) {
        case 'top':
            newTop =
                availableSpace.top > optionCardHeight + gap
                    ? top - optionCardHeight - gap
                    : top + height + gap;
            break;
        case 'down':
            newTop =
                availableSpace.bottom > optionCardHeight + gap
                    ? top + height + gap
                    : top - optionCardHeight - gap;
            if (isAddResourceButton) {
                if (!(availableSpace?.bottom > optionCardHeight + gap)) {
                    newLeft = left + 25;
                    newTop = top + 5;
                }
            }
            break;
        case 'left':
            newLeft =
                availableSpace.left > actualOptionWidth + gap
                    ? left - actualOptionWidth - gap
                    : left + width + gap;
            break;
        case 'right':
            newLeft =
                availableSpace.right > actualOptionWidth + gap
                    ? left + width + gap
                    : left - actualOptionWidth - gap;
            break;
        case 'bottomLeft':
            newTop =
                availableSpace.bottom > optionCardHeight + gap
                    ? top + height + gap
                    : top - optionCardHeight - gap;
            if (optionCardWidth) {
                newLeft = left - optionCardWidth + width;
            }
            break;
        default:
            newTop = top;
            newLeft = left;
    }
    // Ensure menu stays within viewport
    newTop = Math.max(0, Math.min(newTop, window.innerHeight - optionCardHeight - minGap));
    newLeft = Math.max(0, Math.min(newLeft, window.innerWidth - actualOptionWidth - minGap));
    return { top: newTop, left: newLeft };
};
const OptionCard = ({ options, onClick, menuPosition, menuRef, closeDropdown, zIndex = 1500, dropdownPlacement, variant, isAddResourceButton, alignOption, ownerId, dropdownHeight, selectedValue, }) => {
    const themeContext = useContext(ThemeContext);
    const currentTheme = themeContext?.currentTheme;
    const optionCardRef = useRef(null);
    const listRef = useRef(null);
    const optionRefs = useRef({});
    const [optionCardHeight, setOptionCardHeight] = useState(0);
    const [optionCardWidth, setOptionCardWidth] = useState(0);
    useClickOutside(menuRef, closeDropdown, [optionCardRef]);
    useEffect(() => {
        if (optionCardRef.current) {
            setOptionCardHeight(optionCardRef.current.offsetHeight);
            setOptionCardWidth(optionCardRef.current.offsetWidth);
        }
    }, [options]);
    const style = calculatePosition(menuPosition, dropdownPlacement, optionCardHeight, optionCardWidth, isAddResourceButton);
    useEffect(() => {
        if (!selectedValue)
            return;
        const selectedOptionElement = optionRefs.current[selectedValue];
        const container = listRef.current;
        if (selectedOptionElement && container) {
            const elTop = selectedOptionElement.offsetTop;
            const elBottom = elTop + selectedOptionElement.offsetHeight;
            const visibleTop = container.scrollTop;
            const visibleBottom = visibleTop + container.clientHeight;
            // If the option is not visible, scroll to it
            if (elTop < visibleTop || elBottom > visibleBottom) {
                container.scrollTo({
                    top: elTop - container.clientHeight / 2,
                    behavior: 'instant',
                });
            }
        }
    }, [selectedValue]);
    return createPortal(_jsx("div", { className: classNames('ff-option-card', { 'ff-option-card--primary': variant === 'primary' }, { 'ff-option-card--default': variant === 'default' }, currentTheme), "data-owner-id": ownerId, style: { ...style, zIndex, margin: isAddResourceButton ? '0px' : '4px' }, ref: optionCardRef, children: _jsx("div", { className: classNames({ 'ff-option-list': dropdownHeight }), ref: listRef, style: {
                maxHeight: dropdownHeight ? `${dropdownHeight}px` : 'unset',
                overflowY: dropdownHeight ? 'auto' : 'unset',
            }, children: options.map((opt) => !opt.hide && (_jsx("div", { ref: (el) => (optionRefs.current[opt.value] = el), children: _jsx(Tooltip, { title: opt?.tooltipForOption ? opt?.tooltipForOption : '', placement: opt?.tooltipPlacementForOption, children: _jsx(Option, { option: opt, onClick: onClick, alignOption: alignOption }, opt.value) }, opt.value) }, opt.value))) }) }), document.body);
};
const MenuOption = ({ labelName, iconName, tooltipTitle, tooltipPlacement = 'bottom', options = [], onClick = () => { }, onOptionClick = () => { }, iconButtonSize = 24, iconButtonBorderRadius = 7, iconSize = 16, variant = 'light', zIndex = 1500, dropdownPlacement = 'down', optionCardVariant, targetRef = null, treeRowRef, isAddResourceButton, disabled, alignOption = 'left', displayCard = true, didMouseEntered, tableMenu = false, dropdownHeight, selectedValue = '', }) => {
    const [isClicked, setIsClicked] = useState(false);
    const [isHovered, setIsHovered] = useState(false);
    const menuRef = useRef(null);
    const menuIconRef = useRef(null);
    const [menuPosition, setMenuPosition] = useState({
        top: 0,
        left: 0,
        height: 0,
        right: 0,
        width: 0,
    });
    const getTargetElement = useCallback(() => {
        if (!targetRef)
            return null;
        return typeof targetRef === 'string'
            ? document.getElementById(targetRef)
            : getAnchorElement(targetRef);
    }, [targetRef]);
    const closeDropDown = () => setIsClicked(false);
    useEffect(() => {
        const targetElement = getTargetElement();
        if (!targetElement || checkEmpty(options))
            return;
        targetElement.classList.toggle('menu-hover-active', isHovered || isClicked);
        return () => {
            targetElement.classList.remove('menu-hover-active');
        };
    }, [isHovered, isClicked, targetRef, options, getTargetElement]);
    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) &&
                parent.scrollHeight > parent.clientHeight) ||
                (/(auto|scroll|overlay)/.test(overflowX) &&
                    parent.scrollWidth > parent.clientWidth)) {
                return parent;
            }
            parent = parent.parentElement;
        }
        return document.documentElement;
    };
    useEffect(() => {
        if (!menuRef.current)
            return;
        const scrollableParent = getScrollableParent(menuRef.current);
        const handleScroll = () => {
            setIsClicked(false);
        };
        // Attach scroll event to detected parent or window
        scrollableParent?.addEventListener('scroll', handleScroll, {
            passive: true,
        });
        if (scrollableParent !== document.documentElement) {
            // Also attach to window if it's not the detected parent
            window.addEventListener('scroll', handleScroll, { passive: true });
        }
        return () => {
            scrollableParent?.removeEventListener('scroll', handleScroll);
            window.removeEventListener('scroll', handleScroll);
        };
    }, []);
    const onIconClickHandler = () => {
        if (disabled)
            return;
        if (didMouseEntered) {
            didMouseEntered();
        }
        onClick();
        calculateDims();
        setIsClicked((prev) => !prev);
    };
    const handleOptionClick = (option) => {
        treeRowRef?.current?.children[0]?.children[2]?.classList.remove('table-row-add-button');
        onOptionClick(option);
        closeDropDown();
    };
    const calculateDims = () => {
        if (menuIconRef.current) {
            const rect = menuIconRef.current.getBoundingClientRect();
            setMenuPosition({
                top: rect.top + window.scrollY,
                left: rect.left + window.scrollX,
                height: rect.height,
                right: rect.right,
                width: rect.width,
            });
        }
    };
    return (_jsxs("div", { className: "ff-menu-option-container", ref: menuRef, children: [_jsxs("div", { className: "ff-icon-label", "data-tooltip": tooltipTitle, "data-tooltip-placement": tooltipPlacement, children: [_jsx("div", { className: classNames('ff-menuicon-container', {
                            'ff-menuicon-container-clicked': isClicked && displayCard && !checkEmpty(options),
                            dark: variant === 'dark',
                            'ff-menuicon-container-add-resource': isAddResourceButton,
                        }), ref: menuIconRef, onClick: onIconClickHandler, onMouseEnter: () => tableMenu && !disabled && setIsHovered(true), onMouseLeave: () => tableMenu && setIsHovered(false), style: {
                            width: `${iconButtonSize}px`,
                            height: `${iconButtonSize}px`,
                            borderRadius: `${iconButtonBorderRadius}px`,
                        }, children: _jsx(Icon, { height: iconSize, width: iconSize, name: iconName, disabled: disabled, color: displayCard && !checkEmpty(options)
                                ? isClicked === (variant === 'dark')
                                    ? 'var(--menu-option-icon-clicked)'
                                    : 'var(--menu-option-icon-color)'
                                : 'var(--menu-option-icon-clicked)' }) }), labelName && _jsx(Typography, { as: "label", children: labelName })] }), isClicked && displayCard && !checkEmpty(options) && (_jsx(OptionCard, { options: options, onClick: handleOptionClick, menuPosition: menuPosition, menuRef: menuRef, closeDropdown: closeDropDown, zIndex: zIndex, dropdownPlacement: dropdownPlacement, variant: optionCardVariant, isAddResourceButton: isAddResourceButton, alignOption: alignOption, ownerId: (typeof targetRef !== 'string' && targetRef?.current?.id) ||
                    treeRowRef?.current?.id, dropdownHeight: dropdownHeight, selectedValue: selectedValue }))] }));
};
export default MenuOption;
//# sourceMappingURL=MenuOption.js.map