import * as R from "ramda";
import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";

import {
  getInflatedDataSourceUrl,
  getSearchContext,
} from "@applicaster/zapp-react-native-utils/reactHooks";

import {
  mapPromises,
  reducePromises,
} from "@applicaster/zapp-react-native-utils/arrayUtils";

import {
  ZappPipesEntryContext,
  ZappPipesScreenContext,
  ZappPipesSearchContext,
} from "../../Contexts";

export const DATASOURCE_CHUNKS = 10;

export async function loadDatasources(urls: string[][], riverId, dispatch) {
  return reducePromises<string, void>(
    mapPromises<string, void>((url) => {
      if (url) {
        return dispatch(loadPipesData(url, { riverId }));
      }
    }),
    undefined,
    urls
  );
}

export function riverIsCurrentRoute(riverId, route) {
  const routeRiverId = R.compose(R.last, R.split("/"))(route);

  return typeof riverId === "undefined" || routeRiverId === riverId;
}

export const ignoreComponentsWithClearCacheFlag = R.reject(
  R.pathEq(["rules", "clear_cache_on_reload"], true)
);

export const getDatasourceUrl: (
  contexts: {
    screenData?: Record<string, any>;
    entryContext: ReturnType<
      typeof ZappPipesEntryContext.useZappPipesContext
    >[0];
    searchContext: string;
    screenContext: ZappRiver;
  },
  component?: ZappUIComponent
) => string | null = R.curry(
  (
    { screenData, entryContext, searchContext, screenContext },
    component: ZappUIComponent
  ) => {
    const { source, mapping } = R.propOr({}, ["data"], component);

    if (mapping) {
      const contexts = {
        entry: entryContext,
        screen: screenContext || screenData,
        search: getSearchContext(searchContext, mapping),
      };

      return getInflatedDataSourceUrl({ source, mapping, contexts });
    }

    return source;
  }
);

export function usePipesContexts(
  riverId: string,
  route: string
): {
  entryContext: ReturnType<typeof ZappPipesEntryContext.useZappPipesContext>[0];
  searchContext: string;
  screenContext: ZappRiver;
} {
  const isNestedScreen = !riverIsCurrentRoute(riverId, route);

  const routeForEntry = isNestedScreen ? `${route}/river/${riverId}` : route;

  const [entryContext] = ZappPipesEntryContext.useZappPipesContext(
    routeForEntry,
    isNestedScreen
  );

  const [searchContext] = ZappPipesSearchContext.useZappPipesContext();
  const [screenContext] = ZappPipesScreenContext.useZappPipesContext();

  return {
    entryContext,
    searchContext,
    screenContext,
  };
}
