import * as React from "react";
import * as R from "ramda";
import { focusManager } from "./FocusManager";
import { NON_FOCUSABLE_COMPONENTS } from "./const";
import { useFocusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable/index.android";
import { toBooleanWithDefaultTrue } from "../booleanUtils";
import { isNilOrEmpty } from "../reactUtils/helpers";
import { isAndroidTVPlatform } from "../reactUtils";
import { noop } from "../functionUtils";

export function useFocusManager() {
  return focusManager;
}

export function useInitialFocus(
  focused: boolean,
  initialRef?: FocusManager.TouchableReactRef | string,
  options: {
    refsList?: Array<FocusManager.TouchableReactRef> | Array<string>;
    withStateMemory?: boolean;
    initialFocusDirection?: FocusManager.Android.FocusNavigationDirections;
    initialScrollIndex?: number;
  } = {}
): ((index: number) => void) | (() => void) {
  const { withStateMemory, refsList } = options;

  const currentlyFocusedIndex = React.useRef<number>(
    options?.initialScrollIndex || 0
  );

  const setCurrentlyFocusedIndex = React.useCallback(
    (index: number) => (currentlyFocusedIndex.current = index),
    []
  );

  const focusManager = useFocusManager();

  const nextFocus =
    (withStateMemory && refsList?.[currentlyFocusedIndex.current]) ||
    initialRef;

  React.useEffect(() => {
    if (focused && nextFocus) {
      focusManager.setFocus(nextFocus, {
        initialFocusDirection: options?.initialFocusDirection,
      });
    }
  }, [focused, initialRef]);

  if (withStateMemory) {
    return setCurrentlyFocusedIndex;
  }

  return noop;
}

export function useFocusRefs() {
  const { current } = React.useRef([]);

  return current;
}

export function useFocusEffect(onFocus, focusWatcher) {
  const [focused] = focusWatcher;

  React.useLayoutEffect(() => {
    let onBlur = () => null;

    if (focused) {
      onBlur = onFocus?.();
    } else {
      onBlur?.();
    }
  }, focusWatcher);
}

export const isFocusable = (component: ZappEntry | ZappUIComponent | any) =>
  R.tryCatch(
    R.compose(
      R.not,
      R.includes(R.__, NON_FOCUSABLE_COMPONENTS),
      R.prop("component_type")
    ),
    R.T
  )(component);

type Props = {
  component: ZappUIComponent;
  zappPipesData?: ZappPipesData;
} & Record<string, any>;

export const useIsFocusable = (props: Props): void => {
  const { component, zappPipesData } = props;
  const { setIsFocusable } = useFocusable();

  const componentCellsFocusable = toBooleanWithDefaultTrue(
    component?.rules?.component_cells_focusable
  );

  const hideIfDataEmpty = toBooleanWithDefaultTrue(
    component.rules.hide_component_if_data_is_empty
  );

  const hasNoData =
    isNilOrEmpty(zappPipesData?.data) ||
    isNilOrEmpty(zappPipesData?.data?.entry);

  React.useEffect(() => {
    if (isAndroidTVPlatform()) {
      setIsFocusable(
        componentCellsFocusable && (!hasNoData || !hideIfDataEmpty)
      );
    }
  }, [setIsFocusable, componentCellsFocusable, hasNoData]);
};
