import React, {
  ForwardedRef,
  forwardRef,
  ReactElement,
  useEffect,
  useImperativeHandle,
  useRef,
} from 'react';
import {View, TextInput, FocusEvent, BlurEvent} from 'react-native';
import {taggedUserOfPosition} from 'tag-users';
import Text from '@components/Text';
import {useDebounce} from '@hooks/useDebounce';
import {COLORS} from '@shared/colors';
import {isNormalCharacter, isIos, isAndroid} from '@shared/utils';

import {styles} from './styles';
import {getSpecialCharsLength} from './utils';
import {
  CustomizedTextInputProps,
  TextInputComponentProps,
  CustomizedTextInputRefProps,
} from './interfaces';

const DEBOUNCE_DELAY = 2500;
const DEFAULT_BOTTOM_BORDER = 1;

/**
 * @deprecated - Use `_core/TextInput` instead
 */
const TextInputComponent = forwardRef(
  (
    {
      style,
      value,
      placeholder,
      multiline,
      scrollEnabled,
      numberOfLines,
      borderBottomColor,
      autoCapitalize,
      taggedUsers,
      onSubmitEditing,
      noBorder,
      editable = true,
      placeholderTextColor = COLORS.DARK_GRAY,
      autoCorrect = false,
      returnKeyType = 'done',
      borderBottomWidth = DEFAULT_BOTTOM_BORDER,
      ...props
    }: TextInputComponentProps,
    ref: ForwardedRef<TextInput>,
  ) => {
    const addText = (arr: ReactElement[], pos: number, val: string) => {
      const isTaggedUser = taggedUserOfPosition(pos, taggedUsers, true);

      return arr.push(
        <Text key={pos} color={isTaggedUser && COLORS.LIGHT_BLUE}>
          {val}
        </Text>,
      );
    };

    const renderInputCharacters = () => {
      const response: ReactElement[] = [];
      if (!value) {
        return response;
      }
      for (let i = 0; i < value.length; i++) {
        if (isNormalCharacter(value, i)) {
          addText(response, i, value.charAt(i));
        } else {
          const specialCharsLength = getSpecialCharsLength(value, i);
          addText(response, i, value.substring(i, i + specialCharsLength));
          i += specialCharsLength - 1;
        }
      }
      return response;
    };

    return (
      <TextInput
        style={[
          styles.textInput,
          {borderBottomColor, borderBottomWidth},
          isIos && !!numberOfLines && {minHeight: 20 * numberOfLines},
          style,
          noBorder && styles.noBorder,
        ]}
        editable={editable}
        placeholder={editable ? placeholder : ''}
        placeholderTextColor={placeholderTextColor}
        scrollEnabled={!multiline || scrollEnabled}
        onSubmitEditing={onSubmitEditing}
        {...(isAndroid && {numberOfLines})}
        autoCorrect={autoCorrect}
        ref={ref}
        returnKeyType={returnKeyType}
        multiline={multiline}
        {...(!autoCapitalize && {autoCapitalize: 'none'})}
        {...props}>
        {taggedUsers ? renderInputCharacters() : value}
      </TextInput>
    );
  },
);

/**
 * @deprecated - Use `_HuGo/Input` instead
 */
function CustomizedTextInput(
  {
    value,
    maxLength,
    lengthTextStyle,
    onFocus,
    onBlur,
    onDebounceTyping,
    onDebounceStopTyping,
    button,
    containerStyle,
    showMaxLength = true,
    customBorderButtonColor = COLORS.DARK_GRAY,
    ...props
  }: CustomizedTextInputProps,
  ref: ForwardedRef<CustomizedTextInputRefProps>,
) {
  const textInput = useRef<TextInput>(null);
  const inputProps: TextInputComponentProps = {
    value,
    maxLength,
    ...props,
    borderBottomColor: customBorderButtonColor,
    onFocus: (e: FocusEvent) => {
      onFocus && onFocus(e);
    },
    onBlur: (e: BlurEvent) => {
      onBlur && onBlur(e);
    },
  };
  const debouncedValue = useDebounce(value);
  const typingStoppedValue = useDebounce(value, DEBOUNCE_DELAY);

  useEffect(() => {
    debouncedValue && onDebounceTyping && onDebounceTyping();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [debouncedValue]);

  useEffect(() => {
    onDebounceStopTyping && onDebounceStopTyping();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [typingStoppedValue]);

  useImperativeHandle(
    ref,
    () => {
      return {
        focus: () => {
          textInput?.current?.focus?.();
        },
        blur: () => {
          textInput?.current?.blur?.();
        },
        clear: () => {
          textInput?.current?.clear?.();
        },
      };
    },
    [],
  );

  return showMaxLength && maxLength ? (
    <View style={[styles.inputContainer, containerStyle]}>
      <View>
        <TextInputComponent {...inputProps} ref={textInput} />
        {button}
      </View>
      <View style={[styles.alignItems, lengthTextStyle]}>
        <Text color={COLORS.DARK_GRAY}>{`${value?.length}/${maxLength}`}</Text>
      </View>
    </View>
  ) : (
    <TextInputComponent {...inputProps} ref={textInput} />
  );
}

export * from './interfaces';

export default forwardRef(CustomizedTextInput);
