import React, { forwardRef } from 'react';

import type {
  TextInput as RNTextInput,
  TextInputProps as NativeTextInputProps,
  StyleProp,
  ViewStyle,
  TextStyle,
} from 'react-native';

import type { ToolbarMessageState } from './StyledToolbar';
import {
  StyledInput,
  StyledInputContainer,
  StyledPrefix,
  StyledSuffix,
  ToolbarMessageWrapper,
} from './StyledToolbar';
import { useTheme } from '../../theme';

export type ToolbarMessageHandles = Pick<
  RNTextInput,
  'focus' | 'clear' | 'blur' | 'isFocused' | 'setNativeProps'
>;

export interface ToolbarMessageProps extends NativeTextInputProps {
  /**
   * Element to render on the left side of the input, before the user's cursor.
   */
  prefix?: React.ReactNode;
  /**
   * Element to render on the right side of the input.
   */
  suffix?: React.ReactNode;
  /**
   * Additional wrapper style.
   */
  style?: StyleProp<ViewStyle>;
  /**
   * Input text style.
   */
  textStyle?: StyleProp<TextStyle>;
  /**
   * Testing id of the component.
   */
  testID?: string;
  /**
   * Accessibility label for the input (Android).
   */
  accessibilityLabelledBy?: string;
  /**
   *  Placeholder text to display.
   * */
  placeholder?: string;
  /**
   * Whether the input is editable.
   * */
  editable?: boolean;
  /**
   * Whether the input is disabled.
   */
  disabled?: boolean;
  /**
   * The max length of the input.
   * If the max length is set, the input will display the current length and the max length.
   * */
  maxLength?: number;
  /**
   * Component ref.
   */
  ref?: React.Ref<ToolbarMessageHandles>;
}

export const getState = ({
  disabled,
  editable,
  isEmptyValue,
}: {
  disabled?: boolean;
  editable?: boolean;
  isEmptyValue?: boolean;
}): ToolbarMessageState => {
  switch (true) {
    case disabled:
      return 'disabled';
    case !editable:
      return 'readonly';
    case !isEmptyValue:
      return 'filled';
    default:
      return 'default';
  }
};

const ToolbarMessage = forwardRef<ToolbarMessageHandles, ToolbarMessageProps>(
  (props, forwardedRef) => {
    const {
      prefix,
      suffix,
      style,
      testID,
      value,
      defaultValue,
      disabled,
      editable = true,
      textStyle,
      ...nativeProps
    } = props;
    const theme = useTheme();

    const innerTextInput = React.useRef<RNTextInput | undefined | null>(null);

    const displayText = (value !== undefined ? value : defaultValue) ?? '';
    const isEmptyValue = displayText.length === 0;

    React.useImperativeHandle(
      forwardedRef,
      () => ({
        isFocused: () => innerTextInput.current?.isFocused() || false,
        getNativeTextInputRef: () => innerTextInput.current,
        setNativeProps: (args: NativeTextInputProps) =>
          innerTextInput.current?.setNativeProps(args),
        focus: () => innerTextInput.current?.focus(),
        blur: () => innerTextInput.current?.blur(),
        clear: () => innerTextInput.current?.clear(),
      }),
      [innerTextInput.current]
    );

    const state = getState({
      disabled,
      editable,
      isEmptyValue,
    });

    return (
      <ToolbarMessageWrapper testID={testID} style={style}>
        {prefix && (
          <StyledPrefix testID={testID && `${testID}-prefix`}>
            {prefix}
          </StyledPrefix>
        )}
        <StyledInputContainer
          pointerEvents={
            state === 'disabled' || state === 'readonly' ? 'none' : 'auto'
          }
          testID={testID && `${testID}-input-container`}
        >
          <StyledInput
            {...nativeProps}
            value={value}
            defaultValue={defaultValue}
            editable={editable}
            testID={testID && `${testID}-input`}
            ref={(rnTextInputRef) => {
              innerTextInput.current = rnTextInputRef;
            }}
            style={textStyle}
            placeholderTextColor={theme.__hd__.toolbar.colors.placeholder}
          />
        </StyledInputContainer>
        {suffix && (
          <StyledSuffix testID={testID && `${testID}-suffix`}>
            {suffix}
          </StyledSuffix>
        )}
      </ToolbarMessageWrapper>
    );
  }
);

export default ToolbarMessage;
