import type {
  FC,
  ReactNode,
  PropsWithChildren,
  MouseEvent,
} from "react";
import {
  useContext,
  useRef,
  useEffect,
  useMemo,
} from "react";
import { Btn } from "../../btn";
import type { TMapContext } from "../config/types";
import { MapContext } from "../context";
import { getSlot, useVisibility } from "../lib/panel";

export type TMapPanelProps = PropsWithChildren<object>;

/**
 * Внутренний компонент содержимого карты

 * @returns {ReactElement}
 */
const MapPanel: FC<TMapPanelProps> = ({ children }): ReactNode => {

  const {
    getCN, onAction, instanceRef, panelData, 
  } = useContext<TMapContext>(MapContext);

  const prevPanelData = useRef<typeof panelData>(panelData);

  const containerRef = useRef<HTMLElement>(null);

  const { show, hide, isVisible } = useVisibility({
    ref: containerRef,
    delay: 100,
    onShow: () => onOpen(),
    onHide: () => onClose(),
  });

  const stateActions = {
    setIsActive: (isActive: boolean) => isActive ? show() : hide(),
  };

  function onOpen() {
    if (typeof panelData?.onOpen === "function") {
      panelData?.onOpen();
    }
    if (typeof onAction === "function") {
      onAction({
        stateActions,
        el: containerRef.current,
        ref: instanceRef.current,
        getData: () => {
          return {
            type: "panelOpen",
            data: panelData,
          };
        },
      });
    }
  }

  function onClose() {
    if (typeof panelData?.onClose === "function") {
      panelData.onClose();
    }
    if (typeof onAction === "function") {
      onAction({
        stateActions: {},
        el: containerRef.current,
        ref: instanceRef.current,
        getData: () => {
          return {
            type: "panelClose",
            data: panelData,
          };
        },
      });
    }
  }

  const handleBtnClose = (e: MouseEvent) => {
    e.preventDefault();
    hide();
  };

  useEffect(() => {
    if (prevPanelData.current !== panelData) {
      if (panelData) {
        show();
      } else {
        hide();
      }
      prevPanelData.current = panelData;
    }
  }, [ panelData ]);

  const slot = useMemo(() => getSlot(children, panelData), [ children, panelData ]);

  return isVisible && (
    <aside ref={containerRef} className={getCN("panel")}>
      <div className={getCN("panelScroll")}>
        <div className={getCN("panelInner")}>
          {slot}
        </div>
      </div>
      <div className={getCN("panelClose")}>
        <Btn onClick={handleBtnClose} icon={"close"} iconSize={"large"} label={null} />
      </div>
    </aside>
  );

};

export {
  MapPanel,
};
