import * as R from "ramda";
import throttle from "lodash/throttle";
import { toCamelCase } from "@applicaster/zapp-react-native-utils/stringUtils";
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
import { mapKeys } from "@applicaster/zapp-react-native-utils/objectUtils";

const throttleWait = 50;

const throttleOpts = {
  leading: false,
  trailing: true,
};

export const scrollToSelectedIndex = (flatListRef, config, length) =>
  throttle(
    (index: number = 0, viewPosition: number = 0) => {
      const { tab_bar_type: type, component_padding_left: paddingLeft } =
        config;

      const isHorizontal = R.equals("horizontal", type);
      const isLast = R.equals(index, length - 1);
      const isFirst = R.equals(index, 0);

      if (!isHorizontal) {
        flatListRef?.current?.scrollToIndex({
          index: index,
          viewPosition: R.equals(0, viewPosition) ? 0 : 0.5,
          animated: true,
        });
      } else {
        flatListRef?.current?.scrollToIndex({
          index: index,
          viewPosition: R.equals(0, viewPosition) ? 0 : 0.5,
          viewOffset: isHorizontal && (isFirst || isLast) ? paddingLeft : 0,
          animated: true,
        });
      }
    },
    throttleWait,
    throttleOpts
  );

export const getId = R.prop("id");

export const generateFocusableId = (itemId) => `TabBarItem.${itemId}`;

const is = (val) => () => val;

export const getStyleKey = ({ styleKey, focused, selected }) => {
  return R.compose(
    toCamelCase,
    R.tail,
    R.join(""),
    R.when(is(selected), R.prepend("_selected")),
    R.when(is(focused), R.prepend("_focused")),
    R.append(R.__, []),
    R.concat("_")
  )(styleKey);
};

const getPlatformData = (specs) => {
  // can't use optionals in process.env calls because of webpack
  if (process.env.NODE_ENV === "test") {
    try {
      return specs[(global as any)?.__test_platform];
    } catch (e) {
      // this is only used to get a specific value
      // when running test. this is ignored on dev / production
    }
  }

  return platformSelect(specs);
};

const getFontConfig = R.compose(
  R.partition(
    R.compose(
      R.test(/font_family|font_size|line_height|letter_spacing/),
      R.head
    )
  ),
  R.toPairs
);

const platformPrefixes = {
  android_tv: "android_tv_",
  tvos: "tvos_",
  samsung_tv: "samsung_tv_",
  lg_tv: "lg_tv_",
  web: "samsung_tv_",
  default: "samsung_tv_",
};

export function applyFontConfig(config) {
  const [fontConfig, rest] = getFontConfig(config);
  const platformPrefix = getPlatformData(platformPrefixes);

  const fontProps = R.compose(
    mapKeys(R.replace(platformPrefix, "")),
    R.fromPairs,
    R.filter(R.compose(R.contains(platformPrefix), R.head))
  )(fontConfig);

  const otherProps = R.fromPairs(rest);

  return {
    ...fontProps,
    ...otherProps,
  };
}

/* eslint-disable padding-line-between-statements */

export const typePath = R.prop("tab_bar_type");
export const displayTypePath = R.prop("tab_bar_display_mode");
export const itemsAlignmentPath = R.prop("tab_bar_alignment");
export const itemAlignmentPath = R.prop("tab_bar_item_alignment");
export const itemSizeTypePath = R.prop("tab_bar_item_size");

export const isFixed = R.equals("fixed");

export const transformValue = (value, type) => {
  switch (type) {
    case "justifyContent":
    case "alignItems":
      if (value === "left") {
        return "flex-start";
      } else if (value === "right") {
        return "flex-end";
      } else {
        return value;
      }
    case "flexDirectionAsset":
      if (value === "right") return "row-reverse";
      else if (value === "top") return "column";
      else if (value === "bottom") return "column-reverse";
      else return "row";
    case "textAlign":
      return value;
    default:
      // eslint-disable-next-line no-console
      console.log(`type '${type}' doesn\\'t exist`);

      return null;
  }
};

type valueFromConfigType<T> = (
  config: T
) => (key: string, prefix?: string, component?: string) => unknown;

export const valueFromConfig: valueFromConfigType<PlatformConfiguration> = (
  config
) => {
  return (key, prefix = "", component = "tab_bar_item") =>
    config?.[`${component}${prefix.length > 0 ? `_${prefix}` : ""}_${key}`];
};
