/**
 * @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 '@polymer/paper-toggle-button/paper-toggle-button.js';
import '../../shared/gr-button/gr-button.js';
import '../../shared/gr-icons/gr-icons.js';
import '../gr-message/gr-message.js';
import '../../../styles/shared-styles.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.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_html.js';
import {
  KeyboardShortcutMixin,
  Shortcut, ShortcutSection,
} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.js';
import {parseDate} from '../../../utils/date-util.js';
import {MessageTag} from '../../../constants/constants.js';
import {appContext} from '../../../services/app-context.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',
};

/**
 * Computes message author's comments for this change message. The backend
 * sets comment.change_message_id for matching, so this computation is fairly
 * straightforward.
 */
function computeThreads(message, allMessages, changeComments) {
  if ([message, allMessages, changeComments].includes(undefined)) {
    return [];
  }
  if (message._index === undefined) {
    return [];
  }

  return changeComments.getAllThreadsForChange().filter(
      thread => thread.comments.map(comment => {
        // collapse all by default
        comment.collapsed = true;
        return comment;
      }).some(comment => {
        const condition = comment.change_message_id === message.id;
        // Since getAllThreadsForChange() always returns a new copy of
        // all comments we can modify them here without worrying about
        // polluting other threads.
        comment.collapsed = !condition;
        return condition;
      })
  );
}

/**
 * If messages have the same tag, then that influences grouping and whether
 * a message is initally hidden or not, see isImportant(). So we are applying
 * some "magic" rules here in order to hide exactly the right messages.
 *
 * 1. If a message does not have a tag, but is associated with robot comments,
 * then it gets a tag.
 *
 * 2. Use the same tag for some of Gerrit's standard events, if they should be
 * considered one group, e.g. normal and wip patchset uploads.
 *
 * 3. Everything beyond the ~ character is cut off from the tag. That gives
 * tools control over which messages will be hidden.
 */
function computeTag(message) {
  if (!message.tag) {
    const threads = message.commentThreads || [];
    const comments = threads.map(
        t => t.comments.find(c => c.change_message_id === message.id));
    const isRobot = comments.some(c => c && !!c.robot_id);
    return isRobot ? 'autogenerated:has-robot-comments' : undefined;
  }

  if (message.tag === MessageTag.TAG_NEW_WIP_PATCHSET) {
    return MessageTag.TAG_NEW_PATCHSET;
  }
  if (message.tag === MessageTag.TAG_UNSET_ASSIGNEE) {
    return MessageTag.TAG_SET_ASSIGNEE;
  }
  if (message.tag === MessageTag.TAG_UNSET_PRIVATE) {
    return MessageTag.TAG_SET_PRIVATE;
  }
  if (message.tag === MessageTag.TAG_SET_WIP) {
    return MessageTag.TAG_SET_READY;
  }

  return message.tag.replace(/~.*/, '');
}

/**
 * Try to set a revision number that makes sense, if none is set. Just copy
 * over the revision number of the next older message. This is mostly relevant
 * for reviewer updates. Other messages should typically have the revision
 * number already set.
 */
function computeRevision(message, allMessages) {
  if (message._revision_number > 0) return message._revision_number;
  let revision = 0;
  for (const m of allMessages) {
    if (m.date > message.date) break;
    if (m._revision_number > revision) revision = m._revision_number;
  }
  return revision > 0 ? revision : undefined;
}

/**
 * Unimportant messages are initially hidden.
 *
 * Human messages are always important. They have an undefined tag.
 *
 * Autogenerated messages are unimportant, if there is a message with the same
 * tag and a higher revision number.
 */
function computeIsImportant(message, allMessages) {
  if (!message.tag) return true;

  const hasSameTag = m => m.tag === message.tag;
  const revNumber = message._revision_number || 0;
  const hasHigherRevisionNumber = m => m._revision_number > revNumber;
  return !allMessages.filter(hasSameTag).some(hasHigherRevisionNumber);
}

export const TEST_ONLY = {
  computeThreads,
  computeTag,
  computeRevision,
  computeIsImportant,
};

/**
 * @extends PolymerElement
 */
class GrMessagesList extends KeyboardShortcutMixin(
    GestureEventListeners(
        LegacyElementMixin(
            PolymerElement))) {
  static get template() { return htmlTemplate; }

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

  static get properties() {
    return {
      /** @type {?} */
      change: Object,
      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)',
      },

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

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

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

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

    if (!el && this._showAllActivity) {
      console.warn(`Failed to scroll to message: ${messageID}`);
      return;
    }
    if (!el) {
      this._showAllActivity = true;
      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);
  }

  _observeShowAllActivity(showAllActivity) {
    // 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._showAllActivity || message.isImportant;
  }

  /**
   * Merges change messages and reviewer updates into one array. Also processes
   * all messages and updates, aligns or massages some of the properties.
   */
  _computeCombinedMessages(messages, reviewerUpdates, changeComments) {
    const params = [messages, reviewerUpdates, changeComments];
    if (params.some(o => o === undefined)) return [];

    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 || parseDate(messages[mi].date);
      rDate = rDate || 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;
      }
      m.commentThreads = computeThreads(m, combinedMessages, changeComments);
      m._revision_number = computeRevision(m, combinedMessages);
      m.tag = computeTag(m);
    });
    // computeIsImportant() depends on tags and revision numbers already being
    // updated for all messages, so we have to compute this in its own forEach
    // loop.
    combinedMessages.forEach(m => {
      m.isImportant = computeIsImportant(m, combinedMessages);
    });
    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(
          Shortcut.COLLAPSE_ALL_MESSAGES, ShortcutSection.ACTIONS);
    }
    if (_expandAllState === ExpandAllState.EXPAND_ALL) {
      return this.createTitle(
          Shortcut.EXPAND_ALL_MESSAGES, ShortcutSection.ACTIONS);
    }
    return '';
  }

  _highlightEl(el) {
    const highlightedEls =
        dom(this.root).querySelectorAll('.highlighted');
    for (const highlightedEl of highlightedEls) {
      highlightedEl.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);
  }

  _isVisibleShowAllActivityToggle(messages = []) {
    return messages.some(m => !m.isImportant);
  }

  _computeHiddenEntriesCount(messages = []) {
    return messages.filter(m => !m.isImportant).length;
  }

  /**
   * 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
   */
  _onTapShowAllActivityToggle(e) {
    e.preventDefault();
  }
}

customElements.define(GrMessagesList.is,
    GrMessagesList);
