import { useRect } from "@reach/rect";
import { Fragment, useRef } from "react";

import { extendCommonContentStylesheet } from "@devowl-wp/web-cookie-banner";

import { Portal } from "./portal.js";
import { Tooltip } from "./tooltip.js";
import { useStylesheet } from "../contexts/stylesheet.js";

import type { ComponentProps, FC } from "react";

/**
 * A portaled close icon creates a close icon rendered to a given container. This allows
 * you to put the close icon on the top right corner of an `overflow:hidden` container and
 * the tooltip gets rendered correctly.
 *
 * Attention: When using `renderInContainer` the close icon uses an expensive function to
 * observe the position within the container with https://reach.tech/rect/#userect-observe.
 * Only render the close icon when necessery!
 */
const CloseIcon: FC<{
    width: number;
    color: string;
    tooltipText: string;
    tooltipAlways?: boolean;
    framed?: boolean;
    renderInContainer?: ComponentProps<typeof Portal>["renderInContainer"];
    onClick: () => void;
    thickness?: number;
}> = ({ width, color, tooltipText, framed, renderInContainer, tooltipAlways, onClick, thickness = 1 }) => {
    const {
        closeIcon: { framed: framedClass, closeIcon, notPortalIcon, portalIcon, portalPlaceholder },
    } = useStylesheet().extend(...extendCommonContentStylesheet);

    const ref = useRef<HTMLDivElement>();
    const rect = useRect(ref, { observe: !!renderInContainer });

    const style = closeIcon({
        color,
        width,
        thickness,
        ...(rect?.y > 0
            ? {
                  rectX: rect.x,
                  rectY: rect.y,
              }
            : {}),
    });

    const tooltip = (
        <Tooltip
            // Hide on screen readers as the dialog should be closed with "Escape"
            aria-hidden
            title={tooltipText}
            onClick={onClick}
            position={renderInContainer ? (rect?.y > 50 ? "top-left" : "left") : "top-left"}
            always={tooltipAlways}
            className={`${renderInContainer ? portalIcon : notPortalIcon} ${framed ? framedClass : ""}`}
            style={style}
        >
            <span aria-hidden>
                <span />
                <span />
            </span>
        </Tooltip>
    );

    return renderInContainer ? (
        <Fragment>
            <div className={portalPlaceholder} style={style} ref={ref} />
            {rect?.y > 0 && <Portal renderInContainer={renderInContainer}>{tooltip}</Portal>}
        </Fragment>
    ) : (
        tooltip
    );
};

export { CloseIcon };
