import PropTypes from 'prop-types';
import { useCallback, useRef, useState, useEffect, forwardRef } from 'react';
import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import Overlay from 'react-overlays/Overlay';
import Textarea from 'react-textarea-autosize';
import AutosuggestAccountContainer from '../features/compose/containers/autosuggest_account_container';
import AutosuggestEmoji from './autosuggest_emoji';
import { AutosuggestHashtag } from './autosuggest_hashtag';
const textAtCursorMatchesToken = (str, caretPosition) => {
  let word;
  let left  = str.slice(0, caretPosition).search(/\S+$/);
  let right = str.slice(caretPosition).search(/\s/);
  if (right < 0) {
    word = str.slice(left);
  } else {
    word = str.slice(left, right + caretPosition);
  }
  if (!word || word.trim().length < 3 || ['@', ':', '#'].indexOf(word[0]) === -1) {
    return [null, null];
  }
  word = word.trim().toLowerCase();
  if (word.length > 0) {
    return [left + 1, word];
  } else {
    return [null, null];
  }
};
const AutosuggestTextarea = forwardRef(({
  value,
  suggestions,
  disabled,
  placeholder,
  onSuggestionSelected,
  onSuggestionsClearRequested,
  onSuggestionsFetchRequested,
  onChange,
  onKeyUp,
  onKeyDown,
  onPaste,
  onFocus,
  autoFocus = true,
  lang,
}, textareaRef) => {
  const [suggestionsHidden, setSuggestionsHidden] = useState(true);
  const [selectedSuggestion, setSelectedSuggestion] = useState(0);
  const lastTokenRef = useRef(null);
  const tokenStartRef = useRef(0);
  const handleChange = useCallback((e) => {
    const [ tokenStart, token ] = textAtCursorMatchesToken(e.target.value, e.target.selectionStart);
    if (token !== null && lastTokenRef.current !== token) {
      tokenStartRef.current = tokenStart;
      lastTokenRef.current = token;
      setSelectedSuggestion(0);
      onSuggestionsFetchRequested(token);
    } else if (token === null) {
      lastTokenRef.current = null;
      onSuggestionsClearRequested();
    }
    onChange(e);
  }, [onSuggestionsFetchRequested, onSuggestionsClearRequested, onChange, setSelectedSuggestion]);
  const handleKeyDown = useCallback((e) => {
    if (disabled) {
      e.preventDefault();
      return;
    }
    if (e.which === 229 || e.isComposing) {
      // Ignore key events during text composition
      // e.key may be a name of the physical key even in this case (e.x. Safari / Chrome on Mac)
      return;
    }
    switch(e.key) {
    case 'Escape':
      if (suggestions.size === 0 || suggestionsHidden) {
        document.querySelector('.ui').parentElement.focus();
      } else {
        e.preventDefault();
        setSuggestionsHidden(true);
      }
      break;
    case 'ArrowDown':
      if (suggestions.size > 0 && !suggestionsHidden) {
        e.preventDefault();
        setSelectedSuggestion(Math.min(selectedSuggestion + 1, suggestions.size - 1));
      }
      break;
    case 'ArrowUp':
      if (suggestions.size > 0 && !suggestionsHidden) {
        e.preventDefault();
        setSelectedSuggestion(Math.max(selectedSuggestion - 1, 0));
      }
      break;
    case 'Enter':
    case 'Tab':
      // Select suggestion
      if (lastTokenRef.current !== null && suggestions.size > 0 && !suggestionsHidden) {
        e.preventDefault();
        e.stopPropagation();
        onSuggestionSelected(tokenStartRef.current, lastTokenRef.current, suggestions.get(selectedSuggestion));
      }
      break;
    }
    if (e.defaultPrevented || !onKeyDown) {
      return;
    }
    onKeyDown(e);
  }, [disabled, suggestions, suggestionsHidden, selectedSuggestion, setSelectedSuggestion, setSuggestionsHidden, onSuggestionSelected, onKeyDown]);
  const handleBlur = useCallback(() => {
    setSuggestionsHidden(true);
  }, [setSuggestionsHidden]);
  const handleFocus = useCallback((e) => {
    if (onFocus) {
      onFocus(e);
    }
  }, [onFocus]);
  const handleSuggestionClick = useCallback((e) => {
    const suggestion = suggestions.get(e.currentTarget.getAttribute('data-index'));
    e.preventDefault();
    onSuggestionSelected(tokenStartRef.current, lastTokenRef.current, suggestion);
    textareaRef.current?.focus();
  }, [suggestions, onSuggestionSelected, textareaRef]);
  const handlePaste = useCallback((e) => {
    if (e.clipboardData && e.clipboardData.files.length === 1) {
      onPaste(e.clipboardData.files);
      e.preventDefault();
    }
  }, [onPaste]);
  // Show the suggestions again whenever they change and the textarea is focused
  useEffect(() => {
    if (suggestions.size > 0 && textareaRef.current === document.activeElement) {
      setSuggestionsHidden(false);
    }
  }, [suggestions, textareaRef, setSuggestionsHidden]);
  const renderSuggestion = (suggestion, i) => {
    let inner, key;
    if (suggestion.type === 'emoji') {
      inner =