/**
 * @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';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-icons/gr-icons';
import '../gr-message/gr-message';
import '../../../styles/shared-styles';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-messages-list_html';
import {
  KeyboardShortcutMixin,
  Shortcut,
  ShortcutSection,
} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
import {parseDate} from '../../../utils/date-util';
import {MessageTag} from '../../../constants/constants';
import {appContext} from '../../../services/app-context';
import {customElement, property} from '@polymer/decorators';
import {
  ChangeId,
  ChangeMessageId,
  ChangeMessageInfo,
  ChangeViewChangeInfo,
  LabelNameToInfoMap,
  NumericChangeId,
  PatchSetNum,
  RepoName,
  ReviewerUpdateInfo,
  VotingRangeInfo,
} from '../../../types/common';
import {ChangeComments} from '../../diff/gr-comment-api/gr-comment-api';
import {CommentThread, isRobot} from '../../../utils/comment-util';
import {GrMessage, MessageAnchorTapDetail} from '../gr-message/gr-message';
import {PolymerDeepPropertyChange} from '@polymer/polymer/interfaces';
import {DomRepeat} from '@polymer/polymer/lib/elements/dom-repeat';
import {getVotingRange} from '../../../utils/label-util';
import {FormattedReviewerUpdateInfo} from '../../../types/types';

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

interface TagsCountReportInfo {
  [tag: string]: number;
  all: number;
}

type CombinedMessage = Omit<
  FormattedReviewerUpdateInfo | ChangeMessageInfo,
  'tag'
> & {
  _revision_number?: PatchSetNum;
  _index?: number;
  expanded?: boolean;
  isImportant?: boolean;
  commentThreads?: CommentThread[];
  tag?: string;
};

function isChangeMessageInfo(x: CombinedMessage): x is ChangeMessageInfo {
  return (x as ChangeMessageInfo).id !== undefined;
}

function getMessageId(x: CombinedMessage): ChangeMessageId | undefined {
  return isChangeMessageInfo(x) ? x.id : undefined;
}

/**
 * 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: CombinedMessage,
  changeComments: ChangeComments
): CommentThread[] {
  if (message._index === undefined) {
    return [];
  }
  const messageId = getMessageId(message);
  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 === messageId;
        // 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 initially 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: CombinedMessage) {
  if (!message.tag) {
    const threads = message.commentThreads || [];
    const messageId = getMessageId(message);
    const comments = threads.map(t =>
      t.comments.find(c => c.change_message_id === messageId)
    );
    const hasRobotComments = comments.some(isRobot);
    return hasRobotComments ? '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: CombinedMessage,
  allMessages: CombinedMessage[]
): PatchSetNum | undefined {
  if (message._revision_number && message._revision_number > 0)
    return message._revision_number;
  let revision: PatchSetNum = 0 as PatchSetNum;
  for (const m of allMessages) {
    if (m.date > message.date) break;
    if (m._revision_number && 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: CombinedMessage,
  allMessages: CombinedMessage[]
) {
  if (!message.tag) return true;

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

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

export interface GrMessagesList {
  $: {
    messageRepeat: DomRepeat;
  };
}

@customElement('gr-messages-list')
export class GrMessagesList extends KeyboardShortcutMixin(PolymerElement) {
  static get template() {
    return htmlTemplate;
  }

  @property({type: Object})
  change?: ChangeViewChangeInfo;

  @property({type: String})
  changeNum?: ChangeId | NumericChangeId;

  @property({type: Array})
  messages: ChangeMessageInfo[] = [];

  @property({type: Array})
  reviewerUpdates: ReviewerUpdateInfo[] = [];

  @property({type: Object})
  changeComments?: ChangeComments;

  @property({type: String})
  projectName?: RepoName;

  @property({type: Boolean})
  showReplyButtons = false;

  @property({type: Object})
  labels?: LabelNameToInfoMap;

  @property({type: String})
  _expandAllState = ExpandAllState.EXPAND_ALL;

  @property({type: String, computed: '_computeExpandAllTitle(_expandAllState)'})
  _expandAllTitle = '';

  @property({type: Boolean, observer: '_observeShowAllActivity'})
  _showAllActivity = false;

  @property({
    type: Array,
    computed:
      '_computeCombinedMessages(messages, reviewerUpdates, ' +
      'changeComments)',
    observer: '_combinedMessagesChanged',
  })
  _combinedMessages: CombinedMessage[] = [];

  @property({type: Object, computed: '_computeLabelExtremes(labels.*)'})
  _labelExtremes: {[labelName: string]: VotingRangeInfo} = {};

  private readonly reporting = appContext.reportingService;

  scrollToMessage(messageID: string) {
    const selector = `[data-message-id="${messageID}"]`;
    const el = this.shadowRoot!.querySelector(selector) as
      | GrMessage
      | undefined;

    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 as HTMLElement | null;
      offsetParent;
      offsetParent = offsetParent.offsetParent as HTMLElement | null
    ) {
      top += offsetParent.offsetTop;
    }
    window.scrollTo(0, top);
    this._highlightEl(el);
  }

  _observeShowAllActivity() {
    // 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: CombinedMessage) {
    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?: ChangeMessageInfo[],
    reviewerUpdates?: FormattedReviewerUpdateInfo[],
    changeComments?: ChangeComments
  ) {
    if (
      messages === undefined ||
      reviewerUpdates === undefined ||
      changeComments === undefined
    )
      return [];

    let mi = 0;
    let ri = 0;
    let combinedMessages: CombinedMessage[] = [];
    let mDate;
    let rDate;
    for (let i = 0; i < messages.length; i++) {
      // TODO(TS): clone message instead and avoid API object mutation
      (messages[i] as CombinedMessage)._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, 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: boolean) {
    if (this._combinedMessages) {
      for (let i = 0; i < this._combinedMessages.length; i++) {
        this._combinedMessages[i].expanded = exp;
        this.notifyPath(`_combinedMessages.${i}.expanded`);
      }
    }
  }

  _computeExpandAllTitle(_expandAllState?: string) {
    if (_expandAllState === ExpandAllState.COLLAPSE_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: HTMLElement) {
    const highlightedEls = 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');
  }

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

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

  _handleAnchorClick(e: CustomEvent<MessageAnchorTapDetail>) {
    this.scrollToMessage(e.detail.id);
  }

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

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

  /**
   * This method is for reporting stats only.
   */
  _combinedMessagesChanged(combinedMessages?: CombinedMessage[]) {
    if (combinedMessages) {
      if (combinedMessages.length === 0) return;
      const tags = combinedMessages.map(
        message =>
          message.tag || (message as FormattedReviewerUpdateInfo).type || 'none'
      );
      const tagsCounted = tags.reduce(
        (acc, val) => {
          acc[val] = (acc[val] || 0) + 1;
          return acc;
        },
        {all: combinedMessages.length} as TagsCountReportInfo
      );
      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: PolymerDeepPropertyChange<
      LabelNameToInfoMap,
      LabelNameToInfoMap
    >
  ) {
    const extremes: {[labelName: string]: VotingRangeInfo} = {};
    const labels = labelRecord.base;
    if (!labels) {
      return extremes;
    }
    for (const key of Object.keys(labels)) {
      const range = getVotingRange(labels[key]);
      if (range) {
        extremes[key] = range;
      }
    }
    return extremes;
  }

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

declare global {
  interface HTMLElementTagNameMap {
    'gr-messages-list': GrMessagesList;
  }
}
