import React, {
  forwardRef,
  useContext,
  InputHTMLAttributes,
  ForwardRefExoticComponent,
} from "react";
import classNames from "classnames";
import { FormGroupContext } from "../FormGroup/FormGroupContext";
import { bem } from "../../utilities/bem";
import { STATUS_VARIANT, THEME } from "../../types";
import { Box } from "../Box";
import { Icon, SharedFaIconProps, ICON_TYPE } from "../Icon";

export enum INPUT_ICON_POSITION {
  LEFT = "left",
  RIGHT = "right",
}

const cn = "TextInput";

export interface InputBaseProps {
  ref?: any;
  as?: any;
  variant?: STATUS_VARIANT;
  theme?: THEME;
  icon?: ICON_TYPE;
  iconPosition?: INPUT_ICON_POSITION;
  iconProps?: SharedFaIconProps;
}

export interface InputProps
  extends InputBaseProps,
    InputHTMLAttributes<HTMLInputElement> {}

const Input: ForwardRefExoticComponent<InputProps> = forwardRef<
  HTMLInputElement,
  InputProps
>(
  (
    {
      as: Component = "input",
      className,
      icon,
      iconPosition = INPUT_ICON_POSITION.LEFT,
      iconProps,
      id: idProp,
      type,
      variant: variantProp = STATUS_VARIANT.DEFAULT,
      theme: themeProp,
      ...rest
    },
    ref,
  ) => {
    const isTextInput = type !== "radio" && type !== "checkbox";

    const {
      id: idContext,
      variant: variantContext,
      theme: themeContext,
    } = useContext(FormGroupContext);

    const id = idContext || idProp;
    const variant = variantContext || variantProp;
    const theme = themeProp || themeContext;

    const inputClasses = classNames(
      isTextInput && bem(cn),
      bem(cn, { m: variant }),
      bem(cn, { m: theme }),
      icon && bem(cn, { m: `icon-${iconPosition}` }),
      !icon && className,
    );

    const wrapperClasses = classNames(bem(cn, { e: "wrapper" }), className);
    const iconClasses = classNames(
      bem(cn, { e: "icon" }),
      bem(cn, { e: "icon", m: iconPosition }),
    );

    return isTextInput && icon ? (
      <Box className={wrapperClasses}>
        <Component
          ref={ref}
          className={inputClasses}
          id={id}
          type={type}
          {...rest}
        />
        <Icon icon={icon} className={iconClasses} {...iconProps} />
      </Box>
    ) : (
      <Component
        ref={ref}
        className={inputClasses}
        id={id}
        type={type}
        {...rest}
      />
    );
  },
);

export { Input };
