/**
 * @license
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import '../gr-autocomplete-dropdown/gr-autocomplete-dropdown';
import '../gr-cursor-manager/gr-cursor-manager';
import '../gr-overlay/gr-overlay';
import '@polymer/iron-a11y-keys-behavior/iron-a11y-keys-behavior';
import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
import '../../../styles/shared-styles';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-textarea_html';
import {KeyboardShortcutMixin} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
import {appContext} from '../../../services/app-context';
import {customElement, property} from '@polymer/decorators';
import {ReportingService} from '../../../services/gr-reporting/gr-reporting';
import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
import {GrAutocompleteDropdown} from '../gr-autocomplete-dropdown/gr-autocomplete-dropdown';

const MAX_ITEMS_DROPDOWN = 10;

const ALL_SUGGESTIONS: EmojiSuggestion[] = [
  {value: '😊', match: 'smile :)'},
  {value: '👍', match: 'thumbs up'},
  {value: '😄', match: 'laugh :D'},
  {value: '❤️', match: 'heart <3'},
  {value: '😂', match: "tears :')"},
  {value: '🎉', match: 'party'},
  {value: '😎', match: 'cool |;)'},
  {value: '😞', match: 'sad :('},
  {value: '😐', match: 'neutral :|'},
  {value: '😮', match: 'shock :O'},
  {value: '🙏', match: 'pray'},
  {value: '😕', match: 'confused'},
  {value: '👌', match: 'ok'},
  {value: '🔥', match: 'fire'},
  {value: '💯', match: '100'},
  {value: '✔', match: 'check'},
  {value: '😋', match: 'tongue'},
  {value: '😭', match: "crying :'("},
  {value: '🤓', match: 'glasses'},
  {value: '😢', match: 'tear'},
  {value: '😜', match: 'winking tongue ;)'},
];

interface EmojiSuggestion {
  value: string;
  match: string;
  dataValue?: string;
  text?: string;
}

interface ValueChangeEvent {
  value: string;
}

export interface GrTextarea {
  $: {
    textarea: IronAutogrowTextareaElement;
    emojiSuggestions: GrAutocompleteDropdown;
    caratSpan: HTMLSpanElement;
    hiddenText: HTMLDivElement;
  };
}
/**
 * @extends PolymerElement
 */
@customElement('gr-textarea')
export class GrTextarea extends KeyboardShortcutMixin(
  GestureEventListeners(LegacyElementMixin(PolymerElement))
) {
  static get template() {
    return htmlTemplate;
  }

  /**
   * @event bind-value-changed
   */
  @property({type: Boolean})
  autocomplete?: boolean;

  @property({type: Boolean})
  disabled?: boolean;

  @property({type: Number})
  rows?: number;

  @property({type: Number})
  maxRows?: number;

  @property({type: String})
  placeholder?: string;

  @property({type: String, notify: true, observer: '_handleTextChanged'})
  text?: string;

  @property({type: Boolean})
  hideBorder = false;

  /** Text input should be rendered in monospace font.  */
  @property({type: Boolean})
  monospace = false;

  /** Text input should be rendered in code font, which is smaller than the
    standard monospace font. */
  @property({type: Boolean})
  code = false;

  @property({type: Number})
  _colonIndex: number | null = null;

  @property({type: String, observer: '_determineSuggestions'})
  _currentSearchString?: string;

  @property({type: Boolean})
  _hideAutocomplete = true;

  @property({type: Number})
  _index?: number;

  @property({type: Array})
  _suggestions?: EmojiSuggestion[];

  @property({type: Number})
  readonly _verticalOffset = 20;
  // Offset makes dropdown appear below text.

  reporting: ReportingService;

  disableEnterKeyForSelectingEmoji = false;

  get keyBindings() {
    return {
      esc: '_handleEscKey',
      tab: '_handleEnterByKey',
      enter: '_handleEnterByKey',
      up: '_handleUpKey',
      down: '_handleDownKey',
    };
  }

  constructor() {
    super();
    this.reporting = appContext.reportingService;
  }

  /** @override */
  ready() {
    super.ready();
    if (this.monospace) {
      this.classList.add('monospace');
    }
    if (this.code) {
      this.classList.add('code');
    }
    if (this.hideBorder) {
      this.$.textarea.classList.add('noBorder');
    }
  }

  closeDropdown() {
    return this.$.emojiSuggestions.close();
  }

  getNativeTextarea() {
    return this.$.textarea.textarea;
  }

  putCursorAtEnd() {
    const textarea = this.getNativeTextarea();
    // Put the cursor at the end always.
    textarea.selectionStart = textarea.value.length;
    textarea.selectionEnd = textarea.selectionStart;
    this.async(() => {
      textarea.focus();
    });
  }

  _handleEscKey(e: KeyboardEvent) {
    if (this._hideAutocomplete) {
      return;
    }
    e.preventDefault();
    e.stopPropagation();
    this._resetEmojiDropdown();
  }

  _handleUpKey(e: KeyboardEvent) {
    if (this._hideAutocomplete) {
      return;
    }
    e.preventDefault();
    e.stopPropagation();
    this.$.emojiSuggestions.cursorUp();
    this.$.textarea.textarea.focus();
    this.disableEnterKeyForSelectingEmoji = false;
  }

  _handleDownKey(e: KeyboardEvent) {
    if (this._hideAutocomplete) {
      return;
    }
    e.preventDefault();
    e.stopPropagation();
    this.$.emojiSuggestions.cursorDown();
    this.$.textarea.textarea.focus();
    this.disableEnterKeyForSelectingEmoji = false;
  }

  _handleEnterByKey(e: KeyboardEvent) {
    if (this._hideAutocomplete || this.disableEnterKeyForSelectingEmoji) {
      return;
    }
    e.preventDefault();
    e.stopPropagation();
    this._setEmoji(this.$.emojiSuggestions.getCurrentText());
  }

  _handleEmojiSelect(e: CustomEvent) {
    this._setEmoji(e.detail.selected.dataset['value']);
  }

  _setEmoji(text: string) {
    if (this._colonIndex === null) {
      return;
    }
    const colonIndex = this._colonIndex;
    this.text = this._getText(text);
    this.$.textarea.selectionStart = colonIndex + 1;
    this.$.textarea.selectionEnd = colonIndex + 1;
    this.reporting.reportInteraction('select-emoji', {type: text});
    this._resetEmojiDropdown();
  }

  _getText(value: string) {
    if (!this.text) return '';
    return (
      this.text.substr(0, this._colonIndex || 0) +
      value +
      this.text.substr(this.$.textarea.selectionStart)
    );
  }

  /**
   * Uses a hidden element with the same width and styling of the textarea and
   * the text up until the point of interest. Then caratSpan element is added
   * to the end and is set to be the positionTarget for the dropdown. Together
   * this allows the dropdown to appear near where the user is typing.
   */
  _updateCaratPosition() {
    this._hideAutocomplete = false;
    if (typeof this.$.textarea.value === 'string') {
      this.$.hiddenText.textContent = this.$.textarea.value.substr(
        0,
        this.$.textarea.selectionStart
      );
    }

    const caratSpan = this.$.caratSpan;
    this.$.hiddenText.appendChild(caratSpan);
    this.$.emojiSuggestions.positionTarget = caratSpan;
    this._openEmojiDropdown();
  }

  _getFontSize() {
    const fontSizePx = getComputedStyle(this).fontSize || '12px';
    return Number(fontSizePx.substr(0, fontSizePx.length - 2));
  }

  _getScrollTop() {
    return document.body.scrollTop;
  }

  /**
   * _handleKeydown used for key handling in the this.$.textarea AND all child
   * autocomplete options.
   */
  _onValueChanged(e: CustomEvent<ValueChangeEvent>) {
    // Relay the event.
    this.dispatchEvent(
      new CustomEvent('bind-value-changed', {
        detail: e,
        composed: true,
        bubbles: true,
      })
    );

    // If cursor is not in textarea (just opened with colon as last char),
    // Don't do anything.
    if (
      e.currentTarget === null ||
      !(e.currentTarget as IronAutogrowTextareaElement).focused
    ) {
      return;
    }

    const charAtCursor =
      e.detail && e.detail.value
        ? e.detail.value[this.$.textarea.selectionStart - 1]
        : '';
    if (charAtCursor !== ':' && this._colonIndex === null) {
      return;
    }

    // When a colon is detected, set a colon index. We are interested only on
    // colons after space or in beginning of textarea
    if (charAtCursor === ':') {
      if (
        this.$.textarea.selectionStart < 2 ||
        e.detail.value[this.$.textarea.selectionStart - 2] === ' '
      ) {
        this._colonIndex = this.$.textarea.selectionStart - 1;
      }
    }
    if (this._colonIndex === null) {
      return;
    }

    this._currentSearchString = e.detail.value.substr(
      this._colonIndex + 1,
      this.$.textarea.selectionStart - this._colonIndex - 1
    );
    // Under the following conditions, close and reset the dropdown:
    // - The cursor is no longer at the end of the current search string
    // - The search string is an space or new line
    // - The colon has been removed
    // - There are no suggestions that match the search string
    if (
      this.$.textarea.selectionStart !==
        this._currentSearchString.length + this._colonIndex + 1 ||
      this._currentSearchString === ' ' ||
      this._currentSearchString === '\n' ||
      !(e.detail.value[this._colonIndex] === ':') ||
      !this._suggestions ||
      !this._suggestions.length
    ) {
      this._resetEmojiDropdown();
      // Otherwise open the dropdown and set the position to be just below the
      // cursor.
    } else if (this.$.emojiSuggestions.isHidden) {
      this._updateCaratPosition();
    }
    this.$.textarea.textarea.focus();
  }

  _openEmojiDropdown() {
    this.$.emojiSuggestions.open();
    this.reporting.reportInteraction('open-emoji-dropdown');
  }

  _formatSuggestions(matchedSuggestions: EmojiSuggestion[]) {
    const suggestions = [];
    for (const suggestion of matchedSuggestions) {
      suggestion.dataValue = suggestion.value;
      suggestion.text = suggestion.value + ' ' + suggestion.match;
      suggestions.push(suggestion);
    }
    this.set('_suggestions', suggestions);
  }

  _determineSuggestions(emojiText: string) {
    if (!emojiText.length) {
      this._formatSuggestions(ALL_SUGGESTIONS);
      this.disableEnterKeyForSelectingEmoji = true;
    } else {
      const matches = ALL_SUGGESTIONS.filter(suggestion =>
        suggestion.match.includes(emojiText)
      ).slice(0, MAX_ITEMS_DROPDOWN);
      this._formatSuggestions(matches);
      this.disableEnterKeyForSelectingEmoji = false;
    }
  }

  _resetEmojiDropdown() {
    // hide and reset the autocomplete dropdown.
    flush();
    this._currentSearchString = '';
    this._hideAutocomplete = true;
    this.closeDropdown();
    this._colonIndex = null;
    this.$.textarea.textarea.focus();
  }

  _handleTextChanged(text: string) {
    this.dispatchEvent(
      new CustomEvent('value-changed', {detail: {value: text}})
    );
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-textarea': GrTextarea;
  }
}
