import { action, makeObservable, observable } from 'mobx';
import {
  addResizeObserver,
  WixPatternsContainer,
  isMobileDevice,
} from '@wix/bex-core';

export interface TabsResponsiveStateParams {
  container: WixPatternsContainer;
}

export class TabsResponsiveState {
  readonly isMobile: boolean;
  container?: HTMLDivElement;
  // We save the badges in a Map and not in an Array because the badge is optional
  // on a per-tab basis, but we still need to know the index of each badge.
  badges = new Map<number, HTMLSpanElement>();
  mode: 'tabs' | 'dropdown' = 'tabs';

  panelMinWidth = 0;
  itemsCount = 0;
  itemPadding = 32;
  itemMaxWidth = 200;
  itemTextMinWidth = 48;
  itemBadgeMargin = 6;
  itemsMinWidths: number[] = [];

  readonly onResizeThrottled;

  constructor(params: TabsResponsiveStateParams) {
    this.isMobile = isMobileDevice();
    this.onResizeThrottled = params.container.lodash.throttle(
      () => window.requestAnimationFrame(this._onResize),
      300,
    );

    makeObservable(this, {
      mode: observable.ref,
      panelMinWidth: observable.ref,
    });
  }

  getBadgesWidth() {
    return Array.from(this.badges.values()).reduce((sum, badge) => {
      return sum + badge.clientWidth + this.itemBadgeMargin;
    }, 0);
  }

  getItemsMinWidth() {
    const { itemTextMinWidth, itemBadgeMargin } = this;

    return Array.from<number>({ length: this.itemsCount }).map((_, index) => {
      const badge = this.badges.get(index);
      const maybeBadgeWidth = badge ? badge.clientWidth + itemBadgeMargin : 0;

      return itemTextMinWidth + maybeBadgeWidth;
    });
  }

  getPanelMinWidth() {
    const { itemsCount, itemTextMinWidth, itemPadding } = this;

    const itemMinWidth = itemTextMinWidth + itemPadding;
    const badgesWidth = this.getBadgesWidth();

    return itemsCount * itemMinWidth + badgesWidth;
  }

  _externalAvailableWidth: number | null = null;

  setAvailableWidth(width: number) {
    this._externalAvailableWidth = width;
    this._onResize();
  }

  _onResize = action(() => {
    const { container } = this;
    const availableWidth =
      this._externalAvailableWidth ?? container?.clientWidth ?? 0;

    if (process.env.NODE_ENV === 'test') {
      return;
    }
    if (!container) {
      return;
    }

    if (this.isMobile) {
      this.mode = 'dropdown';
      return;
    }

    const nextPanelWidth = this.getPanelMinWidth();

    if (nextPanelWidth !== 0 && nextPanelWidth > this.panelMinWidth) {
      this.itemsMinWidths = this.getItemsMinWidth();
      this.panelMinWidth = nextPanelWidth;
    }

    if (this.panelMinWidth !== 0 && availableWidth < this.panelMinWidth) {
      this.mode = 'dropdown';
    } else {
      this.mode = 'tabs';
    }
  });

  init({
    container,
    itemsCount,
  }: {
    container?: HTMLDivElement;
    itemsCount: number;
  }) {
    this.container = container;
    this.itemsCount = itemsCount;

    const disposer = addResizeObserver(container, this.onResizeThrottled);

    this.onResizeThrottled();

    return () => {
      disposer?.();
    };
  }
}
