import * as React from 'react';
import * as TextControlBase from '@tesseract-design/web-base-textcontrol';

export enum TextInputType {
  TEXT = 'text',
  SEARCH = 'search',
}

export type TextInputProps = Omit<React.HTMLProps<HTMLInputElement>, 'size' | 'type' | 'style'> & {
  /**
   * Short textual description indicating the nature of the component's value.
   */
  label?: React.ReactNode,
  /**
   * Short textual description as guidelines for valid input values.
   */
  hint?: React.ReactNode,
  /**
   * Size of the component.
   */
  size?: TextControlBase.TextControlSize,
  /**
   * Additional description, usually graphical, indicating the nature of the component's value.
   */
  indicator?: React.ReactNode,
  /**
   * Should the component display a border?
   */
  border?: boolean,
  /**
   * Should the component occupy the whole width of its parent?
   */
  block?: boolean,
  /**
   * Type of the component value.
   */
  type?: TextInputType,
  /**
   * Style of the component.
   */
  style?: TextControlBase.TextControlStyle,
  /**
   * Is the label hidden?
   */
  hiddenLabel?: boolean,
}

/**
 * Component for inputting textual values.
 *
 * This component supports multiline input and adjusts its layout accordingly.
 */
export const TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(
  (
    {
      label = '',
      hint = '',
      indicator = null,
      size = TextControlBase.TextControlSize.MEDIUM,
      border = false,
      block = false,
      type = TextInputType.TEXT,
      style = TextControlBase.TextControlStyle.DEFAULT,
      hiddenLabel = false,
      className: _className,
      placeholder: _placeholder,
      as: _as,
      ...etcProps
    }: TextInputProps,
    ref,
  ) => {
    const textInputBaseArgs = React.useMemo<TextControlBase.TextControlBaseArgs>(() => ({
      block,
      border,
      size,
      indicator: Boolean(indicator),
      style,
      resizable: false,
      predefinedValues: false,
    }), [block, border, size, indicator, style]);

    return (
      <div
        className={TextControlBase.Root(textInputBaseArgs)}
      >
        <input
          {...etcProps}
          className={TextControlBase.Input(textInputBaseArgs)}
          ref={ref}
          aria-label={label}
          type={type}
          data-testid="input"
        />
        {
          border && (
            <span
              data-testid="border"
            />
          )
        }
        {
          label && !hiddenLabel && (
            <div
              data-testid="label"
              className={TextControlBase.LabelWrapper(textInputBaseArgs)}
            >
              {label}
            </div>
          )
        }
        {hint && (
          <div
            className={TextControlBase.HintWrapper(textInputBaseArgs)}
            data-testid="hint"
          >
            <div
              className={TextControlBase.Hint()}
            >
              {hint}
            </div>
          </div>
        )}
        {indicator && (
          <div
            className={TextControlBase.IndicatorWrapper(textInputBaseArgs)}
          >
            {indicator}
          </div>
        )}
      </div>
    );
  }
);

TextInput.displayName = 'TextInput';
