/**
 * @license
 * Copyright 2020 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '@polymer/paper-toggle-button/paper-toggle-button';
import '../../shared/gr-button/gr-button';
import '../gr-message/gr-message';
import '../../../styles/gr-paper-styles';
import {parseDate} from '../../../utils/date-util';
import {MessageTag} from '../../../constants/constants';
import {getAppContext} from '../../../services/app-context';
import {customElement, property, state} from 'lit/decorators';
import {
  ChangeId,
  ChangeMessageId,
  ChangeMessageInfo,
  LabelNameToInfoMap,
  NumericChangeId,
  PatchSetNum,
  RepoName,
  VotingRangeInfo,
} from '../../../types/common';
import {CommentThread, isRobot} from '../../../utils/comment-util';
import {GrMessage, MessageAnchorTapDetail} from '../gr-message/gr-message';
import {getVotingRange} from '../../../utils/label-util';
import {
  FormattedReviewerUpdateInfo,
  ParsedChangeInfo,
} from '../../../types/types';
import {commentsModelToken} from '../../../models/comments/comments-model';
import {changeModelToken} from '../../../models/change/change-model';
import {resolve} from '../../../models/dependency';
import {query, queryAll} from '../../../utils/common-util';
import {css, html, LitElement, PropertyValues} from 'lit';
import {sharedStyles} from '../../../styles/shared-styles';
import {subscribe} from '../../lit/subscription-controller';
import {paperStyles} from '../../../styles/gr-paper-styles';
import {when} from 'lit/directives/when';
import {ifDefined} from 'lit/directives/if-defined';
import {
  Shortcut,
  ShortcutSection,
  shortcutsServiceToken,
} from '../../../services/shortcuts/shortcuts-service';
import {GrFormattedText} from '../../shared/gr-formatted-text/gr-formatted-text';
import {Interaction} from '../../../constants/reporting';

/**
 * 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;
}

export 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,
  allThreadsForChange: CommentThread[]
): CommentThread[] {
  if (message._index === undefined) return [];
  const messageId = getMessageId(message);
  return allThreadsForChange.filter(thread =>
    thread.comments.some(comment => comment.change_message_id === messageId)
  );
}

/**
 * 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_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;
}

/**
 * Merges change messages and reviewer updates into one array. Also processes
 * all messages and updates, aligns or massages some of the properties.
 */
function computeCombinedMessages(
  messages: ChangeMessageInfo[],
  reviewerUpdates: FormattedReviewerUpdateInfo[],
  commentThreads: CommentThread[]
): CombinedMessage[] {
  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;
    }
  }

  for (let i = 0; i < combinedMessages.length; i++) {
    const message = combinedMessages[i];
    if (message.expanded === undefined) {
      message.expanded = false;
    }
    message.commentThreads = computeThreads(message, commentThreads);
    message._revision_number = computeRevision(message, combinedMessages);
    message.tag = computeTag(message);
  }
  // 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;
}

/**
 * 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 = {
  computeTag,
  computeRevision,
  computeIsImportant,
};

@customElement('gr-messages-list')
export class GrMessagesList extends LitElement {
  // TODO: Evaluate if we still need to have display: flex on the :host and
  // .header.
  static override get styles() {
    return [
      sharedStyles,
      paperStyles,
      css`
        :host {
          display: flex;
          justify-content: space-between;
        }
        .header {
          align-items: center;
          border-bottom: 1px solid var(--border-color);
          display: flex;
          justify-content: space-between;
          padding: var(--spacing-s) var(--spacing-l);
        }
        .highlighted {
          animation: 3s fadeOut;
        }
        @keyframes fadeOut {
          0% {
            background-color: var(--emphasis-color);
          }
          100% {
            background-color: var(--view-background-color);
          }
        }
        .container {
          align-items: center;
          display: flex;
        }
        .hiddenEntries {
          color: var(--deemphasized-text-color);
        }
        gr-message:not(:last-of-type) {
          border-bottom: 1px solid var(--border-color);
        }
      `,
    ];
  }

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

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

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

  @state()
  private change?: ParsedChangeInfo;

  @state()
  private changeNum?: ChangeId | NumericChangeId;

  @state()
  private commentThreads: CommentThread[] = [];

  @state()
  private projectName?: RepoName;

  @state()
  expandAllState = ExpandAllState.EXPAND_ALL;

  // Private but used in tests.
  @state()
  showAllActivity = false;

  @state()
  private combinedMessages: CombinedMessage[] = [];

  // Private but used in tests.
  readonly getCommentsModel = resolve(this, commentsModelToken);

  private readonly changeModel = resolve(this, changeModelToken);

  private readonly reporting = getAppContext().reportingService;

  private readonly getShortcutsService = resolve(this, shortcutsServiceToken);

  constructor() {
    super();
    subscribe(
      this,
      () => this.getCommentsModel().threads$,
      x => {
        this.commentThreads = x;
      }
    );
    subscribe(
      this,
      () => this.changeModel().change$,
      x => {
        this.change = x;
      }
    );
    subscribe(
      this,
      () => this.changeModel().repo$,
      x => {
        this.projectName = x;
      }
    );
    subscribe(
      this,
      () => this.changeModel().changeNum$,
      x => {
        this.changeNum = x;
      }
    );
    // for COMMENTS_AUTOCLOSE logging purposes only
    this.reporting.reportInteraction(
      Interaction.COMMENTS_AUTOCLOSE_MESSAGES_LIST_CREATED
    );
  }

  override updated(): void {
    // for COMMENTS_AUTOCLOSE logging purposes only
    const messages = this.shadowRoot!.querySelectorAll('gr-message');
    if (messages.length > 0) {
      this.reporting.reportInteraction(
        Interaction.COMMENTS_AUTOCLOSE_MESSAGES_LIST_UPDATED,
        {uid: messages[0].uid}
      );
    }
  }

  override willUpdate(changedProperties: PropertyValues): void {
    if (
      changedProperties.has('messages') ||
      changedProperties.has('reviewerUpdates') ||
      changedProperties.has('commentThreads')
    ) {
      this.combinedMessages = computeCombinedMessages(
        this.messages ?? [],
        this.reviewerUpdates ?? [],
        this.commentThreads ?? []
      );
      this.combinedMessagesChanged();
    }
  }

  override render() {
    const labelExtremes = this.computeLabelExtremes();
    return html`${this.renderHeader()}
    ${this.combinedMessages
      .filter(m => this.showAllActivity || m.isImportant)
      .map(
        message => html`<gr-message
          .change=${this.change}
          .changeNum=${this.changeNum}
          .message=${message}
          .commentThreads=${message.commentThreads}
          .projectName=${this.projectName}
          @message-anchor-tap=${this.handleAnchorClick}
          .labelExtremes=${labelExtremes}
          data-message-id=${ifDefined(getMessageId(message) as String)}
        ></gr-message>`
      )}`;
  }

  private renderHeader() {
    return html`<div class="header">
      <div id="showAllActivityToggleContainer" class="container">
        ${when(
          this.combinedMessages.some(m => !m.isImportant),
          () => html`
            <paper-toggle-button
              class="showAllActivityToggle"
              ?checked=${this.showAllActivity}
              @change=${this.handleShowAllActivityChanged}
              aria-labelledby="showAllEntriesLabel"
              role="switch"
              @click=${this.onTapShowAllActivityToggle}
            ></paper-toggle-button>
            <div id="showAllEntriesLabel" aria-hidden="true">
              <span>Show all entries</span>
              <span class="hiddenEntries" ?hidden=${this.showAllActivity}>
                (${this.combinedMessages.filter(m => !m.isImportant).length}
                hidden)
              </span>
            </div>
            <span class="transparent separator"></span>
          `
        )}
      </div>
      <gr-button
        id="collapse-messages"
        link
        .title=${this.computeExpandAllTitle()}
        @click=${this.handleExpandCollapseTap}
      >
        ${this.expandAllState}
      </gr-button>
    </div>`;
  }

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

    if (!el && this.showAllActivity) {
      this.reporting.error(
        new Error(`Failed to scroll to message: ${messageID}`)
      );
      return;
    }
    if (!el || !el.message) {
      this.showAllActivity = true;
      setTimeout(() => this.scrollToMessage(messageID));
      return;
    }

    el.message.expanded = true;
    // Must wait for message to expand and render before we can scroll to it
    el.requestUpdate();
    await el.updateComplete;
    await query<GrFormattedText>(el, 'gr-formatted-text.message')
      ?.updateComplete;
    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);
  }

  private handleShowAllActivityChanged(e: Event) {
    this.showAllActivity = (e.target as HTMLInputElement).checked ?? false;
  }

  private refreshMessages() {
    for (const message of queryAll<GrMessage>(this, 'gr-message')) {
      message.requestUpdate();
    }
  }

  private computeExpandAllTitle() {
    if (this.expandAllState === ExpandAllState.COLLAPSE_ALL) {
      return this.getShortcutsService().createTitle(
        Shortcut.COLLAPSE_ALL_MESSAGES,
        ShortcutSection.ACTIONS
      );
    }
    if (this.expandAllState === ExpandAllState.EXPAND_ALL) {
      return this.getShortcutsService().createTitle(
        Shortcut.EXPAND_ALL_MESSAGES,
        ShortcutSection.ACTIONS
      );
    }
    return '';
  }

  // Private but used in tests.
  highlightEl(el: HTMLElement) {
    const highlightedEls =
      this.shadowRoot?.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');
  }

  // Private but used in tests.
  handleExpandCollapse(expand: boolean) {
    this.expandAllState = expand
      ? ExpandAllState.COLLAPSE_ALL
      : ExpandAllState.EXPAND_ALL;
    if (!this.combinedMessages) return;
    for (let i = 0; i < this.combinedMessages.length; i++) {
      this.combinedMessages[i].expanded = expand;
    }
    this.refreshMessages();
  }

  private handleExpandCollapseTap(e: Event) {
    e.preventDefault();
    this.handleExpandCollapse(
      this.expandAllState === ExpandAllState.EXPAND_ALL
    );
  }

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

  /**
   * Called when this.combinedMessages has changed.
   */
  private combinedMessagesChanged() {
    if (this.combinedMessages.length === 0) return;
    this.refreshMessages();
    const tags = this.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: this.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.
   * Private but used in tests.
   */
  computeLabelExtremes() {
    const extremes: {[labelName: string]: VotingRangeInfo} = {};
    if (!this.labels) {
      return extremes;
    }
    for (const key of Object.keys(this.labels)) {
      const range = getVotingRange(this.labels[key]);
      if (range) {
        extremes[key] = range;
      }
    }
    return extremes;
  }

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

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