import * as React from "react";
import * as R from "ramda";
import { View, ViewStyle } from "react-native";

import { platformSelect } from "../../reactUtils";

type Data = Array<any>;

type RenderItemProps = { index: number } & Record<string, any>;

export const useSequentialRenderItem = (data: Data) => {
  const [componentsState, dispatch] = React.useReducer(
    (state, { data, type }) => {
      if (state[data]) {
        return state;
      }

      switch (type) {
        case "set":
          return R.set(R.lensIndex(data), true)(state);
        case "reset":
          return data;
        default:
          return state;
      }
    },
    new Array(data.length).fill(false)
  );

  React.useLayoutEffect(() => {
    dispatch({ type: "reset", data: new Array(data.length).fill(false) });
  }, [data]);

  const arePreviousComponentsReady = React.useCallback(
    (index) => R.compose(R.all(R.equals(true)), R.take(index))(componentsState),
    [componentsState]
  );

  const onLoadFinished = React.useCallback((id) => {
    dispatch({ type: "set", data: id });
  }, []);

  const renderItem = React.useCallback(
    R.curry(
      // eslint-disable-next-line react/display-name
      (renderItem, props: RenderItemProps) => {
        const { index, item } = props;

        const readyToDisplay =
          index === 0 ? true : arePreviousComponentsReady(index);

        const displayStyle: ViewStyle = {
          display: readyToDisplay ? "flex" : "none",
        };

        const readyStyle = {
          visibility: readyToDisplay ? "visible" : "hidden",
        } as ViewStyle;

        const style = platformSelect({
          tvos: readyStyle,
          samsung_tv: readyStyle,
          lg_tv: readyStyle,
          default: displayStyle,
        });

        const shouldRenderEmptyIfNotReady = platformSelect({
          tvos: true,
          samsung_tv: true,
          lg_tv: true,
          default: false,
        });

        if (!readyToDisplay && shouldRenderEmptyIfNotReady) {
          return <View />;
        }

        return (
          <View
            key={item?.id || index}
            style={style as {}}
            testID={`sequential-river-wrapper-${item?.id}`}
          >
            {renderItem({
              ...props,
              onLoadFinished: () => {
                onLoadFinished(index);
              },
            })}
          </View>
        );
      }
    ),
    [componentsState, arePreviousComponentsReady, onLoadFinished]
  );

  return {
    renderItem,
    allLoaded: R.all(R.equals(true), componentsState),
    componentsState,
  };
};
