import React, { forwardRef, useRef, useState, useEffect } from "react";
import { mergeRefs } from "../_util/merge-refs";
import { InputProps, Input } from "../input";
import { callBoth } from "../_util/call-both";
import { noop } from "../_util/noop";

interface TagSelectInputProps extends InputProps {
  maxWidth: number;
  reservedWidth?: number;
}

export const TagSelectInput = forwardRef(function TagSelectInput(
  {
    value,
    maxWidth,
    reservedWidth = 6,
    placeholder = "",
    style = {},
    onInput = noop,
    ...props
  }: TagSelectInputProps,
  ref: React.Ref<HTMLInputElement>
) {
  const inputRef = useRef<HTMLInputElement>(null);
  const mirrorRef = useRef<HTMLSpanElement>(null);
  const [width, setWidth] = useState<number>(0);
  const [fullInputValue, setFullInputValue] = useState<string>(value);

  useEffect(() => {
    setFullInputValue(value);
  }, [value]);

  useEffect(() => {
    mirrorRef.current.innerText = fullInputValue || placeholder || "";
    const width = mirrorRef.current.clientWidth;
    setWidth(width > maxWidth ? maxWidth : width);
  }, [fullInputValue, maxWidth, placeholder]);

  const handleInput = e => setFullInputValue(e.currentTarget.value);
  return (
    <>
      <Input
        {...props}
        value={value}
        placeholder={placeholder}
        onInput={callBoth(handleInput, onInput)}
        style={{ ...style, width: width + reservedWidth }}
        ref={mergeRefs(ref, inputRef)}
      />
      <span
        ref={mirrorRef}
        style={{
          position: "absolute",
          top: -9999,
          left: 0,
          whiteSpace: "pre",
          fontSize: 12,
        }}
      />
    </>
  );
});

TagSelectInput.displayName = "TagSelectInput";
