import React, { useCallback, useEffect, useState } from "react";
import * as R from "ramda";
import { Appearance, Platform, StyleSheet, TextInput } from "react-native";
import { isFunction } from "@applicaster/zapp-react-native-utils/functionUtils";
import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
import { useIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";

type Props = Partial<{
  style: any;
  onChangeText: any;
  onChange: any;
  secureTextEntry: boolean;
  onEndEditing: any;
  onBlur: any;
  onPress: any;
  additional: any;
  onKeyDown: any;
  value: any;
}> &
  TextInput["props"];

function getInitialColorScheme() {
  try {
    return Appearance.getColorScheme();
  } catch (e) {
    // skipping appearance on platforms which don't support it
  }
}

function TextInputTV(props: Props, ref) {
  const {
    onChangeText,
    onChange,
    style,
    secureTextEntry,
    onEndEditing,
    onBlur,
    onPress,
    additional,
  } = props;

  const [colorScheme, setColorScheme] = useState(getInitialColorScheme());
  const isRTL = useIsRTL();

  const onColorChange = useCallback(
    ({ colorScheme: color }) => {
      if (color !== colorScheme) {
        setColorScheme(color);
      }
    },
    [colorScheme]
  );

  useEffect(() => {
    if (Appearance) {
      const subscription = Appearance.addChangeListener(onColorChange);

      return () => subscription.remove();
    }
  }, [colorScheme]);

  const isWebPlatform = isWeb();

  const onChangeTextPolyfill = (onChange) =>
    R.compose(onChange, R.path(["target", "value"]));

  const getOnChangeText = () => {
    if (isWebPlatform) return undefined;

    return { onChangeText };
  };

  const getOnChange = () => {
    if (isWebPlatform) {
      if (onChange) return { onChange };

      if (onChangeText) {
        return { onChange: onChangeTextPolyfill(onChangeText) };
      }
    }

    return undefined;
  };

  const getStyle = () => {
    if (!style) return undefined;

    if (isWebPlatform) {
      if (StyleSheet && isFunction(StyleSheet.flatten)) {
        const styles = StyleSheet.flatten(style);

        if (isRTL && !!styles.textAlign) {
          const textAlign =
            styles.textAlign === "center"
              ? styles.textAlign
              : styles.textAlign === "left"
                ? "right"
                : "left";

          return { style: { ...styles, textAlign } };
        }

        return { style: styles };
      }
    }

    return { style };
  };

  const getSecureTextEntry = () => {
    if (typeof secureTextEntry === "undefined") return undefined;

    if (isWebPlatform) {
      if (secureTextEntry === true) {
        return { type: "password" };
      }

      return undefined;
    }

    return { secureTextEntry };
  };

  const getOnEndEditing = () => {
    if (!onEndEditing) return undefined;

    if (isWebPlatform) {
      return { onBlur: onBlur || onEndEditing };
    }

    return { onEndEditing };
  };

  const getOnPress = () => {
    if (!onPress) return undefined;

    if (isWebPlatform) {
      return { onClick: onPress };
    }

    return { onPress };
  };

  const getProps = () =>
    R.when(
      R.always(isWebPlatform),
      R.omit([
        "onChangeText",
        "secureTextEntry",
        "onEndEditing",
        "onPress",
        "placeholderTextColor",
      ])
    )(props);

  const inputProps = {
    ...getProps(),
    ...getStyle(),
    ...getOnChange(),
    ...getOnChangeText(),
    ...getSecureTextEntry(),
    ...getOnEndEditing(),
    ...getOnPress(),
  };

  if (
    Platform.OS === "ios" &&
    Platform.isTV &&
    colorScheme &&
    !inputProps.keyboardAppearance
  ) {
    inputProps.keyboardAppearance = colorScheme;
  }

  return isWebPlatform ? (
    <>
      {additional && additional()}
      <input ref={ref} {...inputProps} />
    </>
  ) : (
    <TextInput ref={ref} {...inputProps} />
  );
}

// $FlowFixMe
export const TextInputTv = React.forwardRef<TextInput, Props>(TextInputTV);
