import { makeListOf } from "@applicaster/zapp-react-native-utils/arrayUtils";
import { isFirstComponentGallery } from "@applicaster/zapp-react-native-utils/componentsUtils";
import { once } from "ramda";

const INITIAL_NUMBER_TO_LOAD = 3;

// Infer the values of COMPONENT_LOADING_STATE as a type
type ComponentLoadingState =
  (typeof COMPONENT_LOADING_STATE)[keyof typeof COMPONENT_LOADING_STATE];

export const COMPONENT_LOADING_STATE = {
  UNKNOWN: "UNKNOWN",
  LOADED_WITH_SUCCESS: "LOADED_WITH_SUCCESS",
  LOADED_WITH_FAILURE: "LOADED_WITH_FAILURE",
} as const;

// Function to get the number of loaded components
const getNumberOfLoaded = (states: ComponentLoadingState[]): number => {
  return states.filter((value) => value !== COMPONENT_LOADING_STATE.UNKNOWN)
    .length;
};

const getNumberOfComponentsWaitToLoadBeforePresent = (
  componentsToRender: ZappUIComponent[]
): number => {
  // when Gallery is the first component, no need to wait the others
  if (isFirstComponentGallery(componentsToRender)) {
    return 1;
  }

  return Math.min(INITIAL_NUMBER_TO_LOAD, componentsToRender.length);
};

export class ScreenRevealManager {
  public numberOfComponentsWaitToLoadBeforePresent: number;
  private renderingState: Array<ComponentLoadingState>;
  private callback: Callback;

  constructor(componentsToRender: ZappUIComponent[], callback: Callback) {
    this.numberOfComponentsWaitToLoadBeforePresent =
      getNumberOfComponentsWaitToLoadBeforePresent(componentsToRender);

    this.renderingState = makeListOf<ComponentLoadingState>(
      COMPONENT_LOADING_STATE.UNKNOWN,
      this.numberOfComponentsWaitToLoadBeforePresent
    );

    this.callback = once(callback);
  }

  onLoadFinished = (index: number): void => {
    this.renderingState[index] = COMPONENT_LOADING_STATE.LOADED_WITH_SUCCESS;

    if (
      getNumberOfLoaded(this.renderingState) >=
      this.numberOfComponentsWaitToLoadBeforePresent
    ) {
      this.setIsReadyToShow();
    }
  };

  onLoadFailed = (index: number): void => {
    this.renderingState[index] = COMPONENT_LOADING_STATE.LOADED_WITH_FAILURE;

    if (
      getNumberOfLoaded(this.renderingState) >=
      this.numberOfComponentsWaitToLoadBeforePresent
    ) {
      this.setIsReadyToShow();
    }
  };

  setIsReadyToShow = (): void => {
    this.callback();
  };
}
