import React, {
  ChangeEvent,
  FocusEvent,
  ReactElement,
  TextareaHTMLAttributes,
} from 'react';
import css from '../../utils/css';

import StyledTextArea, {
  AutoResizeWrapper,
  HiddenTextArea,
} from './StyledTextArea';
import { getThemeState } from './utils';

import { CommonProps } from '../common';
import { fromUndefinedable, getOrElse, map } from '../../fp/Option';
import { pipe } from '../../fp/function';

export interface TextAreaProps
  extends Omit<CommonProps, 'id'>,
    TextareaHTMLAttributes<HTMLTextAreaElement> {
  /**
   * Specify the [automated assistance](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) in filling out form field values by the browser.
   */
  autoComplete?: string;
  /**
   * Specify the input element should automatically get focus when it is mounted.
   */
  autoFocus?: boolean;
  /**
   * Automatically resize element's height to fit the content. This only works if this component is controlled by specifying `value` & `onChange`.
   */
  autoResize?: boolean;
  /**
   * Whether the textarea is disabled.
   */
  disabled?: boolean;
  /**
   * Id of <input> element.
   */
  id?: string;
  /**
   * Whether the input is invalid
   */
  invalid?: boolean;
  /**
   * Name of <input> element, is used to refer to the form data for submission.
   */
  name?: string;
  /**
   * Blur event handler.
   */
  onBlur?: (e: FocusEvent<HTMLTextAreaElement>) => void;
  /**
   * Change event handler. Use `event.target.value` for new value.
   */
  onChange?: (e: ChangeEvent<HTMLTextAreaElement>) => void;
  /**
   * Focus event handler.
   */
  onFocus?: (e: FocusEvent<HTMLTextAreaElement>) => void;
  /**
   * Placeholder text in the absence of any value.
   */
  placeholder?: string;
  /**
   * Text size of textarea.
   */
  size?: 'small' | 'medium' | 'large';
  /**
   * The textarea's content value.
   */
  value?: string;
}

const TextArea = ({
  value,
  onChange,
  onFocus,
  onBlur,
  autoResize = true,
  size = 'medium',
  disabled = false,
  invalid = false,
  placeholder,
  name,
  id,
  className,
  style,
  sx = {},
  autoComplete,
  autoFocus,
  'data-test-id': dataTestId,
  ...textAreaAttrs
}: TextAreaProps): ReactElement => {
  const textarea = (
    <StyledTextArea
      {...textAreaAttrs}
      value={value}
      onChange={onChange}
      placeholder={placeholder}
      disabled={disabled}
      onFocus={onFocus}
      onBlur={onBlur}
      name={name}
      id={id}
      autoComplete={autoComplete}
      autoFocus={autoFocus}
      autoResize={autoResize}
      themeState={getThemeState({ disabled, invalid })}
      themeSize={size}
    />
  );

  if (autoResize === true) {
    return (
      <AutoResizeWrapper
        className={className}
        style={{ ...style, ...css(sx) }}
        data-test-id={dataTestId}
      >
        <HiddenTextArea themeSize={size}>
          {pipe(
            value,
            fromUndefinedable,
            map(v => v.concat('\n')),
            getOrElse(() => '')
          )}
        </HiddenTextArea>
        {textarea}
      </AutoResizeWrapper>
    );
  }

  return textarea;
};

export default TextArea;
