import {
  WixPatternsContainer,
  CollectionState,
  FiltersMap,
} from '@wix/bex-core';
import { GridBaseState } from './GridBaseState';
import { action, computed, makeObservable, observable, reaction } from 'mobx';
import { ToolbarCollectionState } from './ToolbarCollectionState';
import {
  FoldersAndItemsCollectionsState,
  FoldersAndItemsCollectionsStateInitParams,
  PartialAllFilters,
} from './FoldersAndItemsCollectionsState';
import {
  GridSizePreset,
  sideGridSizePreset,
  topGridSizePreset,
} from './gridSizePresets';
import { GridFoldersBIReporter } from './GridFoldersBIReporter';
import { ICollectionComponentState } from './ICollectionComponentState';

export interface GridFoldersStateParams<
  T1,
  F1 extends FiltersMap,
  T2,
  F2 extends FiltersMap,
> {
  readonly items: CollectionState<T1, F1>;
  readonly folders: CollectionState<T2, F2>;
  readonly container: WixPatternsContainer;
  readonly toolbar?: ToolbarCollectionState<T1, PartialAllFilters<F1, F2>>;
  readonly collections?: FoldersAndItemsCollectionsState<T1, F1, T2, F2>;
}

interface GridFoldersStateInitParams
  extends FoldersAndItemsCollectionsStateInitParams {}

export class GridFoldersState<
  T1,
  F1 extends FiltersMap,
  T2,
  F2 extends FiltersMap,
> implements ICollectionComponentState
{
  readonly container;
  readonly toolbar;
  readonly items;
  readonly folders;
  readonly collections;
  readonly bi;

  readonly _subGrids = [] as GridBaseState<any, any>[];
  readonly _sizePreset = undefined as undefined | GridSizePreset;

  showAllFolders = false;

  constructor(params: GridFoldersStateParams<T1, F1, T2, F2>) {
    this.container = params.container;

    this.toolbar =
      params.toolbar ??
      new ToolbarCollectionState({
        collection: params.items as CollectionState<T1, {}> as CollectionState<
          T1,
          PartialAllFilters<F1, F2>
        >,
        container: params.container,
        componentType: 'GridFolders',
      });

    this.collections =
      params.collections ??
      new FoldersAndItemsCollectionsState({
        ...params,
        toolbar: this.toolbar,
      });

    this.items = new GridBaseState({
      collection: params.items,
      container: params.container,
      toolbar: this.toolbar as ToolbarCollectionState<unknown, Partial<F1>>,
      sizePreset: topGridSizePreset,
      parentState: this,
      layoutType: 'grid',
    });

    this.folders = new GridBaseState({
      collection: params.folders,
      container: params.container,
      toolbar: this.toolbar as ToolbarCollectionState<unknown, Partial<F2>>,
      sizePreset: sideGridSizePreset,
      parentState: this,
      layoutType: 'grid',
    });

    this.bi = new GridFoldersBIReporter({
      state: this,
    });

    makeObservable(this, {
      showAllFolders: observable.ref,
      foldersLocalLimit: computed,
      effectiveFoldersLocalLimit: computed,
      showToggleShowAllLessButton: computed,
      showItemsSection: computed,
      showItemsSectionHeader: computed,
      showFoldersSection: computed,
      showFoldersSectionHeader: computed,
      showLoadingSection: computed,
    });
  }

  toggleShowAllFolders = action(() => {
    this.showAllFolders = !this.showAllFolders;
    this.bi.onToggleShowAllButtonClick();
  });

  get foldersLocalLimit() {
    return this.folders.columnsCount * 2;
  }

  get effectiveFoldersLocalLimit() {
    return this.showAllFolders ? null : this.folders.columnsCount * 2;
  }

  get showToggleShowAllLessButton() {
    return this.collections.folders.result.size > this.foldersLocalLimit;
  }

  get showFoldersSectionHeader() {
    return this.showToggleShowAllLessButton || this.showItemsSection;
  }

  get showItemsSection() {
    return (
      !this.collections.items.result.isEmptyAndNotFetching &&
      !this.collections.hasFoldersOnlyActiveFilters &&
      (!this.showAllFolders || this.folders.collection.fetchedLastPage)
    );
  }

  get initTask() {
    return this.toolbar.initTask;
  }

  get showErrorState() {
    return this.toolbar.multi.showErrorState;
  }

  get errorStatus() {
    return this.toolbar.multi.errorStatus;
  }

  retryErrorState = action(() => this.toolbar.retryErrorState());

  get showLoadingState() {
    return this.toolbar.multi.showLoadingState;
  }

  get showEmptyState() {
    return this.collections.showEmptyState;
  }

  get hasAvailableItems() {
    return this.collections.hasAvailableItems;
  }

  get resultOriginQuerySearch() {
    return this.collections.resultOriginQuerySearch;
  }

  get hasNonPersistentActiveFilters() {
    return this.collections.hasNonPersistentActiveFilters;
  }

  get showItemsSectionHeader() {
    return this.showFoldersSection;
  }

  get showFoldersSection() {
    return (
      !this.collections.folders.result.isEmptyAndNotFetching &&
      !this.collections.hasItemsOnlyActiveFilters
    );
  }

  get showLoadingSection() {
    const {
      collections: { hasFoldersOnlyActiveFilters, hasItemsOnlyActiveFilters },
      toolbar: { initTask, multi },
    } = this;

    const isLoadingToolbarAndCollection = () =>
      (multi.showInitialLoader && initTask.status.isLoading) ||
      initTask.status.isIdle;

    return (
      !hasFoldersOnlyActiveFilters &&
      !hasItemsOnlyActiveFilters &&
      (multi.showRefreshLoader || isLoadingToolbarAndCollection())
    );
  }

  init(params: GridFoldersStateInitParams) {
    const disposers = [
      this.collections.init(params),
      reaction(
        () => this.effectiveFoldersLocalLimit,
        (effectiveFoldersLocalLimit) => {
          this.folders._localLimit = effectiveFoldersLocalLimit;
        },
        {
          fireImmediately: true,
        },
      ),
    ];

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