import React, { FC, useRef, useState } from "react";

interface SubComponents {
    Button: FC<DropdownButtonProps>;
    Panel: FC<DropdownPanelProps>;
}

export interface DropdownProps {
    children: [
        React.ReactComponentElement<SubComponents["Button"]>,
        React.ReactComponentElement<SubComponents["Panel"]>
    ];
    position?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
    open?: boolean;
    onChange?: (value: boolean) => void;
}

export interface DropdownPanelProps {
    children: React.ReactNode;
}

export interface DropdownButtonProps {
    children: React.ReactNode;
}

export const Dropdown: FC<DropdownProps> & SubComponents = ({
    children,
    position = "bottom-right",
    open: openProp,
    onChange,
}) => {
    const [internalOpen, setInternalOpen] = useState(false);
    const buttonRef = useRef<HTMLDivElement | null>(null);

    let open = internalOpen;
    let toggleOpen = () => setInternalOpen(prev => !prev);
    if (openProp !== undefined) {
        open = openProp;
        toggleOpen = () => onChange?.(!open);
    }

    let positionValues = {};
    if (buttonRef.current) {
        const { height: buttonHeight } =
            buttonRef.current.getBoundingClientRect();
        const [vertical, horizontal] = position.split("-");
        positionValues = {
            [vertical === "bottom" ? "top" : "bottom"]: buttonHeight,
            [horizontal === "right" ? "left" : "right"]: 0,
        };
    }

    return (
        <div className="w-fit h-fit relative">
            <div ref={buttonRef} className="w-fit h-fit" onClick={toggleOpen}>
                {children[0]}
            </div>
            <div
                className={`w-fit h-fit absolute z-10 ${
                    open ? "block" : "hidden"
                }`}
                style={{
                    ...positionValues,
                }}
            >
                {children[1]}
            </div>
        </div>
    );
};

Dropdown.Panel = ({ children }) => {
    return <>{children}</>;
};

Dropdown.Button = ({ children }) => {
    return <>{children}</>;
};

export default Dropdown;
