import { ComponentType } from 'react';
import { WixPatternsContainer, SidePanelState } from '@wix/bex-core';
import { action, makeObservable, observable, reaction } from 'mobx';

type PanelId =
  | 'filters'
  | 'customColumns'
  | 'multiLevelSorting'
  | 'customFields';

export interface SidePanelsStateParams {
  container: WixPatternsContainer;
  panelGroupName: string;
}

export class SidePanelsState {
  readonly container;

  readonly sidePanelComponents;
  readonly sidePanel;
  readonly panelGroupName;

  constructor(params: SidePanelsStateParams) {
    this.container = params.container;
    this.panelGroupName = params.panelGroupName;
    this.sidePanel = new SidePanelState();

    this.sidePanelComponents = observable.map<string, ComponentType>([], {
      deep: false,
    });
    makeObservable(this, {
      registerSidePanel: action,
    });
  }

  _getPanelUniqueId(panelId: PanelId) {
    const {
      container: {
        environment: { componentId },
      },
      panelGroupName,
    } = this;

    return [componentId, panelGroupName, panelId].filter(Boolean).join('/');
  }

  get isFiltersPanelOpen() {
    return this.sidePanel.transition.data === this._getPanelUniqueId('filters');
  }

  registerSidePanel(panelId: PanelId, component: ComponentType) {
    const { sidePanelComponents } = this;

    sidePanelComponents.set(this._getPanelUniqueId(panelId), component);
  }

  openSidePanel(panelId: PanelId) {
    const { sidePanel } = this;
    sidePanel._open(this._getPanelUniqueId(panelId));
  }

  closeSidePanel = () => {
    this.sidePanel.close();
  };

  toggleSidePanel(panelId: PanelId) {
    const { sidePanel } = this;
    const panelUniqueId = this._getPanelUniqueId(panelId);

    if (sidePanel.currentPanelId === panelUniqueId && sidePanel.isOpen) {
      this.closeSidePanel();
    } else {
      this.openSidePanel(panelId);
    }

    return sidePanel.isOpen;
  }

  init() {
    const { sidePanel, sidePanelComponents } = this;

    const disposers = [
      reaction(
        () => sidePanelComponents.entries(),
        () => {
          if (
            sidePanel.currentPanelId &&
            !sidePanelComponents.has(sidePanel.currentPanelId)
          ) {
            sidePanel.close();
          }
        },
        {
          fireImmediately: true,
        },
      ),
    ];

    return () => {
      disposers.forEach((d) => d());
    };
  }
}
