/**
 * @license
 * Copyright (C) 2020 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 '@polymer/paper-toggle-button/paper-toggle-button.js';
import '../../core/gr-reporting/gr-reporting.js';
import '../../shared/gr-button/gr-button.js';
import '../gr-message/gr-message.js';
import '../../../styles/shared-styles.js';
import {dom} 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-messages-list-experimental_html.js';
import {KeyboardShortcutBehavior} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
import {util} from '../../../scripts/util.js';

/**
 * The content of the enum is also used in the UI for the button text.
 *
 * @enum {string}
 */
const ExpandAllState = {
  EXPAND_ALL: 'Expand All',
  COLLAPSE_ALL: 'Collapse All',
};

/**
 * @extends Polymer.Element
 */
class GrMessagesListExperimental extends mixinBehaviors( [
  KeyboardShortcutBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-messages-list-experimental'; }

  static get properties() {
    return {
      changeNum: Number,
      /**
       * These are just the change messages. They are combined with reviewer
       * updates below. So _combinedMessages is the more important property.
       */
      messages: {
        type: Array,
        value() { return []; },
      },
      /**
       * These are just the reviewer updates. They are combined with change
       * messages above. So _combinedMessages is the more important property.
       */
      reviewerUpdates: {
        type: Array,
        value() { return []; },
      },
      changeComments: Object,
      projectName: String,
      showReplyButtons: {
        type: Boolean,
        value: false,
      },
      labels: Object,

      /**
       * Keeps track of the state of the "Expand All" toggle button. Note that
       * you can individually expand/collapse some messages without affecting
       * the toggle button's state.
       *
       * @type {ExpandAllState}
       */
      _expandAllState: {
        type: String,
        value: ExpandAllState.EXPAND_ALL,
      },
      _expandAllTitle: {
        type: String,
        computed: '_computeExpandAllTitle(_expandAllState)',
      },

      _hideAutomated: {
        type: Boolean,
        value: false,
        observer: '_hideAutomatedChanged',
      },
      /**
       * The merged array of change messages and reviewer updates.
       */
      _combinedMessages: {
        type: Array,
        computed: '_computeCombinedMessages(messages, reviewerUpdates)',
        observer: '_combinedMessagesChanged',
      },

      _labelExtremes: {
        type: Object,
        computed: '_computeLabelExtremes(labels.*)',
      },
    };
  }

  scrollToMessage(messageID) {
    const selector = `[data-message-id="${messageID}"]`;
    const el = this.shadowRoot.querySelector(selector);

    if (!el && !this._hideAutomated) {
      console.warn(`Failed to scroll to message: ${messageID}`);
      return;
    }
    if (!el) {
      this._hideAutomated = false;
      setTimeout(() => this.scrollToMessage(messageID));
      return;
    }

    el.set('message.expanded', true);
    let top = el.offsetTop;
    for (let offsetParent = el.offsetParent;
      offsetParent;
      offsetParent = offsetParent.offsetParent) {
      top += offsetParent.offsetTop;
    }
    window.scrollTo(0, top);
    this._highlightEl(el);
  }

  _isAutomated(message) {
    const isReviewerUpdate =
        !!(message.reviewer || message.type === 'REVIEWER_UPDATE');
    const isAutoGenerated =
        !!(message.tag && message.tag.startsWith('autogenerated'));
    return isReviewerUpdate || isAutoGenerated;
  }

  _hideAutomatedChanged(hideAutomated) {
    // We have to call render() such that the dom-repeat filter picks up the
    // change.
    this.$.messageRepeat.render();
  }

  /**
   * Filter for the dom-repeat of combinedMessages.
   */
  _isMessageVisible(message) {
    return !(this._hideAutomated && this._isAutomated(message));
  }

  /**
   * Merges change messages and reviewer updates into one array.
   */
  _computeCombinedMessages(messages, reviewerUpdates) {
    messages = messages || [];
    reviewerUpdates = reviewerUpdates || [];
    let mi = 0;
    let ri = 0;
    let combinedMessages = [];
    let mDate;
    let rDate;
    for (let i = 0; i < messages.length; i++) {
      messages[i]._index = i;
    }

    while (mi < messages.length || ri < reviewerUpdates.length) {
      if (mi >= messages.length) {
        combinedMessages = combinedMessages.concat(reviewerUpdates.slice(ri));
        break;
      }
      if (ri >= reviewerUpdates.length) {
        combinedMessages = combinedMessages.concat(messages.slice(mi));
        break;
      }
      mDate = mDate || util.parseDate(messages[mi].date);
      rDate = rDate || util.parseDate(reviewerUpdates[ri].date);
      if (rDate < mDate) {
        combinedMessages.push(reviewerUpdates[ri++]);
        rDate = null;
      } else {
        combinedMessages.push(messages[mi++]);
        mDate = null;
      }
    }
    combinedMessages.forEach(m => {
      if (m.expanded === undefined) {
        m.expanded = false;
      }
    });
    return combinedMessages;
  }

  _updateExpandedStateOfAllMessages(exp) {
    if (this._combinedMessages) {
      for (let i = 0; i < this._combinedMessages.length; i++) {
        this._combinedMessages[i].expanded = exp;
        this.notifyPath(`_combinedMessages.${i}.expanded`);
      }
    }
  }

  _computeExpandAllTitle(_expandAllState) {
    if (_expandAllState === ExpandAllState.COLLAPSED_ALL) {
      return this.createTitle(
          this.Shortcut.COLLAPSE_ALL_MESSAGES, this.ShortcutSection.ACTIONS);
    }
    if (_expandAllState === ExpandAllState.EXPAND_ALL) {
      return this.createTitle(
          this.Shortcut.EXPAND_ALL_MESSAGES, this.ShortcutSection.ACTIONS);
    }
    return '';
  }

  _highlightEl(el) {
    const highlightedEls =
        dom(this.root).querySelectorAll('.highlighted');
    for (const highlighedEl of highlightedEls) {
      highlighedEl.classList.remove('highlighted');
    }
    function handleAnimationEnd() {
      el.removeEventListener('animationend', handleAnimationEnd);
      el.classList.remove('highlighted');
    }
    el.addEventListener('animationend', handleAnimationEnd);
    el.classList.add('highlighted');
  }

  /**
   * @param {boolean} expand
   */
  handleExpandCollapse(expand) {
    this._expandAllState = expand ? ExpandAllState.COLLAPSE_ALL
      : ExpandAllState.EXPAND_ALL;
    this._updateExpandedStateOfAllMessages(expand);
  }

  _handleExpandCollapseTap(e) {
    e.preventDefault();
    this.handleExpandCollapse(
        this._expandAllState === ExpandAllState.EXPAND_ALL);
  }

  _handleAnchorClick(e) {
    this.scrollToMessage(e.detail.id);
  }

  _hasAutomatedMessages(messages) {
    if (!messages) { return false; }
    for (const message of messages) {
      if (this._isAutomated(message)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Computes message author's file comments for change's message. The backend
   * sets comment.change_message_id for matching, so this computation is fairly
   * straightforward.
   *
   * @param {!Object} changeComments changeComment object, which includes
   *     a method to get all published comments (including robot comments),
   *     which returns a Hash of arrays of comments, filename as key.
   * @param {!Object} message
   * @return {!Object} Hash of arrays of comments, filename as key.
   */
  _computeCommentsForMessage(changeComments, message) {
    if ([changeComments, message].some(arg => arg === undefined)) {
      return {};
    }
    const comments = changeComments.getAllPublishedComments();
    if (message._index === undefined || !comments || !this.messages) {
      return {};
    }
    const idFilter = comment => comment.change_message_id === message.id;

    const msgComments = {};
    for (const file in comments) {
      if (!comments.hasOwnProperty(file)) { continue; }
      const filtered = comments[file].filter(idFilter);
      if (filtered.length) msgComments[file] = filtered;
    }
    return msgComments;
  }

  /**
   * This method is for reporting stats only.
   */
  _combinedMessagesChanged(combinedMessages) {
    if (combinedMessages) {
      if (combinedMessages.length === 0) return;
      const tags = combinedMessages.map(
          message => message.tag || message.type ||
              (message.comments ? 'comments' : 'none'));
      const tagsCounted = tags.reduce((acc, val) => {
        acc[val] = (acc[val] || 0) + 1;
        return acc;
      }, {all: combinedMessages.length});
      this.$.reporting.reportInteraction('messages-count', tagsCounted);
    }
  }

  /**
   * Compute a mapping from label name to objects representing the minimum and
   * maximum possible values for that label.
   */
  _computeLabelExtremes(labelRecord) {
    const extremes = {};
    const labels = labelRecord.base;
    if (!labels) { return extremes; }
    for (const key of Object.keys(labels)) {
      if (!labels[key] || !labels[key].values) { continue; }
      const values = Object.keys(labels[key].values)
          .map(v => parseInt(v, 10));
      values.sort((a, b) => a - b);
      if (!values.length) { continue; }
      extremes[key] = {min: values[0], max: values[values.length - 1]};
    }
    return extremes;
  }

  /**
   * Work around a issue on iOS when clicking turns into double tap
   */
  _onTapAutomatedMessageToggle(e) {
    e.preventDefault();
  }
}

customElements.define(GrMessagesListExperimental.is,
    GrMessagesListExperimental);
