/**
 * @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.
 */
(function() {
  'use strict';

  const MAX_ITEMS_DROPDOWN = 10;

  const ALL_SUGGESTIONS = [
    {value: '😊', match: 'smile :)'},
    {value: '👍', match: 'thumbs up'},
    {value: '😄', match: 'laugh :D'},
    {value: '🎉', match: 'party'},
    {value: '😞', match: 'sad :('},
    {value: '😂', match: 'tears :\')'},
    {value: '🙏', match: 'pray'},
    {value: '😐', match: 'neutral :|'},
    {value: '😮', match: 'shock :O'},
    {value: '👎', match: 'thumbs down'},
    {value: '😎', match: 'cool |;)'},
    {value: '😕', match: 'confused'},
    {value: '👌', match: 'ok'},
    {value: '🔥', match: 'fire'},
    {value: '👊', match: 'fistbump'},
    {value: '💯', match: '100'},
    {value: '💔', match: 'broken heart'},
    {value: '🍺', match: 'beer'},
    {value: '✔', match: 'check'},
    {value: '😋', match: 'tongue'},
    {value: '😭', match: 'crying :\'('},
    {value: '🐨', match: 'koala'},
    {value: '🤓', match: 'glasses'},
    {value: '😆', match: 'grin'},
    {value: '💩', match: 'poop'},
    {value: '😢', match: 'tear'},
    {value: '😒', match: 'unamused'},
    {value: '😉', match: 'wink ;)'},
    {value: '🍷', match: 'wine'},
    {value: '😜', match: 'winking tongue ;)'},
  ];

  /**
   * @appliesMixin Gerrit.FireMixin
   * @appliesMixin Gerrit.KeyboardShortcutMixin
   * @extends Polymer.Element
   */
  class GrTextarea extends Polymer.mixinBehaviors( [
    Gerrit.FireBehavior,
    Gerrit.KeyboardShortcutBehavior,
  ], Polymer.GestureEventListeners(
      Polymer.LegacyElementMixin(
          Polymer.Element))) {
    static get is() { return 'gr-textarea'; }
    /**
     * @event bind-value-changed
     */

    static get properties() {
      return {
        autocomplete: Boolean,
        disabled: Boolean,
        rows: Number,
        maxRows: Number,
        placeholder: String,
        text: {
          type: String,
          notify: true,
          observer: '_handleTextChanged',
        },
        hideBorder: {
          type: Boolean,
          value: false,
        },
        /** Text input should be rendered in monspace font.  */
        monospace: {
          type: Boolean,
          value: false,
        },
        /** Text input should be rendered in code font, which is smaller than the
          standard monospace font. */
        code: {
          type: Boolean,
          value: false,
        },
        /** @type {?number} */
        _colonIndex: Number,
        _currentSearchString: {
          type: String,
          observer: '_determineSuggestions',
        },
        _hideAutocomplete: {
          type: Boolean,
          value: true,
        },
        _index: Number,
        _suggestions: Array,
        // Offset makes dropdown appear below text.
        _verticalOffset: {
          type: Number,
          value: 20,
          readOnly: true,
        },
      };
    }

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

    /** @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) {
      if (this._hideAutocomplete) { return; }
      e.preventDefault();
      e.stopPropagation();
      this._resetEmojiDropdown();
    }

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

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

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

    _handleEmojiSelect(e) {
      this._setEmoji(e.detail.selected.dataset.value);
    }

    _setEmoji(text) {
      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) {
      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;
      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 parseInt(fontSizePx.substr(0, fontSizePx.length - 2),
          10);
    }

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

    /**
     * _handleKeydown used for key handling in the this.$.textarea AND all child
     * autocomplete options.
     */
    _onValueChanged(e) {
      // Relay the event.
      this.fire('bind-value-changed', e);

      // If cursor is not in textarea (just opened with colon as last char),
      // Don't do anything.
      if (!e.currentTarget.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;
        }
      }

      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.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) {
      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) {
      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.
      Polymer.dom.flush();
      this._currentSearchString = '';
      this._hideAutocomplete = true;
      this.closeDropdown();
      this._colonIndex = null;
      this.$.textarea.textarea.focus();
    }

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

  customElements.define(GrTextarea.is, GrTextarea);
})();
