import { observer } from 'mobx-react-lite';
import { SidePanelWidth } from '@wix/bex-core';
import { useWixPatternsContainer, usePageContext } from '@wix/bex-core/react';
import { SlidingModal } from '../SlidingModal';
import React, { useEffect, useMemo } from 'react';
import { reaction } from 'mobx';
import { SidePanelModalItem } from './SidePanelModalItem';
import { SidePanelsState } from '../../state/SidePanelsState';

export interface SidePanelModalProps {
  top: number;
  left?: number;
  state: SidePanelsState;
}

function _SidePanelModal(props: SidePanelModalProps) {
  const { top, left, state } = props;
  const {
    onSidePanelOpen,
    closeSidePanel,
    isPanelLayout,
    useRelativeSidePanel,
  } = useWixPatternsContainer();
  const pageState = usePageContext();

  const { sidePanel, sidePanelComponents } = state;

  const { isOpen } = sidePanel;

  const width = useMemo(
    () => (isPanelLayout ? '100%' : SidePanelWidth),
    [isPanelLayout],
  );

  const style = useMemo(
    () => ({
      top,
      ...(useRelativeSidePanel
        ? {
            right: isPanelLayout ? undefined : 0,
          }
        : {
            left: isPanelLayout
              ? 0
              : left != null
              ? left - SidePanelWidth
              : undefined,
          }),
      bottom: 0,
      overflow: 'hidden',
      width,
    }),
    [top, left, width],
  );

  useEffect(() => {
    return reaction(
      () => sidePanel.isOpen,
      (sidePanelOpen) => {
        pageState.sidePanelOpen = sidePanelOpen;
      },
    );
  }, []);

  useEffect(() => {
    const onGlobalSidePanelOpenSub = onSidePanelOpen?.(() => {
      state.closeSidePanel();
    });

    const disposers = [
      reaction(
        () => sidePanel.isOpen,
        (sidePanelShow) => {
          if (sidePanelShow) {
            closeSidePanel?.();
          }
        },
      ),
    ];

    return () => {
      onGlobalSidePanelOpenSub?.remove();
      disposers.forEach((d) => d?.());
    };
  }, []);

  return (
    <SlidingModal
      dataHook="cairo-side-panel-modal"
      transitionStatus={sidePanel.transition.status}
      style={style}
      appendTo={isPanelLayout || useRelativeSidePanel ? 'parent' : undefined}
      overlay={isPanelLayout}
      contentRef={(el) => {
        sidePanel.focus.modalElement = el;
      }}
      onExited={() => {
        sidePanel.transition.setStatus('exited');
      }}
      onEntered={() => {
        sidePanel.transition.setStatus('entered');
      }}
      onEntering={() => {
        sidePanel.transition.setStatus('entering');
      }}
      onExiting={() => {
        sidePanel.transition.setStatus('exiting');
      }}
      width={SidePanelWidth}
      isOpen={isOpen}
      onRequestClose={() => {
        sidePanel.close();
      }}
    >
      {Array.from(sidePanelComponents.entries()).map(([key, ComponentType]) => {
        return (
          <SidePanelModalItem key={key} id={key} width={width} state={state}>
            <ComponentType />
          </SidePanelModalItem>
        );
      })}
    </SlidingModal>
  );
}

export const SidePanelModal = observer(_SidePanelModal);
