/**
 * @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.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 {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';
import {KeyboardShortcutBehavior} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
import {appContext} from '../../../services/app-context.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 ;)'},
];

/**
 * @extends PolymerElement
 */
class GrTextarea extends mixinBehaviors( [
  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',
    };
  }

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