/* eslint-disable dot-notation */
import React, { useRef, useState } from "react";
import classNames from "classnames";
import { StyledProps, Omit } from "../_type";
import { ControlledProps, useDefaultValue } from "../form/controlled";
import { forwardRefWithStatics } from "../_util/forward-ref-with-statics";
import { useConfig } from "../_util/config-context";
import { SizeType } from "../_type/Size";
import { noop } from "../_util/noop";
import { KeyMap } from "../_util/key-map";

/**
 * TextArea 组件支持的属性。
 *
 * 除表格中列出的属性外，支持透传原生 `<textarea>` 标签支持的属性。
 */
export interface TextAreaProps
  extends ControlledProps<string>,
    StyledProps,
    Omit<
      React.TextareaHTMLAttributes<HTMLTextAreaElement>,
      "onChange" | "value" | "defaultValue"
    > {
  /**
   * 占位符
   */
  placeholder?: string;

  /**
   * 是否禁用
   * @default false
   */
  disabled?: boolean;

  /**
   * 是否为只读模式
   * @default false
   */
  readonly?: boolean;

  /**
   * 最大输入长度
   */
  maxLength?: number;

  /**
   * 输入框尺寸，使用 `full` 撑满容器宽度
   */
  size?: SizeType;

  /**
   * 行数
   */
  rows?: number;

  /**
   * 是否展示字数
   */
  showCount?: boolean;

  /**
   * 按下回车键的回调
   * @since 2.7.0
   */
  onPressEnter?: (value: string, event: React.KeyboardEvent) => void;
}

export const TextArea = forwardRefWithStatics(
  (props: TextAreaProps, ref: React.Ref<HTMLTextAreaElement>) => {
    const { classPrefix } = useConfig();
    const {
      placeholder,
      disabled,
      readonly,
      size,
      className,
      style,
      value,
      onChange,
      showCount,
      onCompositionStart = noop,
      onCompositionEnd = noop,
      onKeyPress = noop,
      onPressEnter = noop,
      ...restProps
    } = useDefaultValue(props, "");

    const composingRef = useRef(false);
    // 记录 `composition` 事件过程中值以实现受控
    const [composingRefValue, setComposingValue] = useState<string>("");

    const inputClassName = classNames(`${classPrefix}-textarea`, {
      [className]: className,
      [`size-${size === "full" ? `${size}-width` : size}`]: size,
    });

    const hasRows = restProps.rows;

    const inputProps: React.TextareaHTMLAttributes<HTMLTextAreaElement> = {
      placeholder,
      className: inputClassName,
      readOnly: readonly,
      disabled,
      // 受样式限制 rows 属性没有生效
      style: hasRows ? { height: "auto", ...(style || {}) } : style,
      value: composingRef.current ? composingRefValue : value,
      onChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => {
        if (composingRef.current) {
          setComposingValue(event.target.value);
        } else {
          onChange(event.target.value, { event });
        }
      },
      onCompositionStart: (
        event: React.CompositionEvent<HTMLTextAreaElement>
      ) => {
        composingRef.current = true;
        onCompositionStart(event);
      },
      onCompositionEnd: (
        event: React.CompositionEvent<HTMLTextAreaElement>
      ) => {
        if (composingRef.current) {
          composingRef.current = false;
          onChange(event.currentTarget.value, { event });
        }
        setComposingValue("");
        onCompositionEnd(event);
      },
      onKeyPress: (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
        if (event.key === KeyMap.Enter) {
          onPressEnter(event.currentTarget.value, event);
        }
        onKeyPress(event);
      },
      ...restProps,
    };

    const component = <textarea ref={ref} {...inputProps} />;
    if (showCount) {
      const max = inputProps.maxLength;
      const len = value ? String(value).length : 0;
      return (
        <div
          className={`${classPrefix}-textarea-group`}
          style={size === "full" ? { width: "100%" } : undefined}
        >
          {component}
          <label className={`${classPrefix}-textarea__label`}>
            {max ? `${len} / ${max}` : len}
          </label>
        </div>
      );
    }
    return component;
  },
  {
    /**
     * 在表单布局中，和 label 的默认对齐方式
     */
    defaultLabelAlign: "middle",
  }
);

TextArea.displayName = "TextArea";
