/**
 * @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 '../../../scripts/bundled-polymer.js';

import '../../../behaviors/fire-behavior/fire-behavior.js';
import '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
import '../gr-autocomplete-dropdown/gr-autocomplete-dropdown.js';
import '../gr-cursor-manager/gr-cursor-manager.js';
import '../gr-overlay/gr-overlay.js';
import '@polymer/iron-a11y-keys-behavior/iron-a11y-keys-behavior.js';
import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea.js';
import '../../../styles/shared-styles.js';
import '../../core/gr-reporting/gr-reporting.js';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-textarea_html.js';

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 mixinBehaviors( [
  Gerrit.FireBehavior,
  Gerrit.KeyboardShortcutBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get template() { return htmlTemplate; }

  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.
    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);
