/**
 * @license
 * Copyright 2018 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../../styles/shared-styles';
import '../../shared/gr-comment-thread/gr-comment-thread';
import '../../shared/gr-dropdown-list/gr-dropdown-list';
import {SpecialFilePath} from '../../../constants/constants';
import {
  AccountDetailInfo,
  AccountInfo,
  CommentThread,
  NumericChangeId,
  UrlEncodedCommentId,
  isDraft,
} from '../../../types/common';
import {ChangeMessageId} from '../../../api/rest-api';
import {
  getCommentAuthors,
  getMentionedThreads,
  hasHumanReply,
  isDraftThread,
  isMentionedThread,
  isRobotThread,
  isUnresolved,
  lastUpdated,
} from '../../../utils/comment-util';
import {pluralize} from '../../../utils/string-util';
import {assertIsDefined} from '../../../utils/common-util';
import {
  CommentTabState,
  TabState,
  ValueChangedEvent,
} from '../../../types/events';
import {DropdownItem} from '../../shared/gr-dropdown-list/gr-dropdown-list';
import {GrAccountChip} from '../../shared/gr-account-chip/gr-account-chip';
import {css, html, LitElement, PropertyValues} from 'lit';
import {customElement, property, queryAll, state} from 'lit/decorators.js';
import {sharedStyles} from '../../../styles/shared-styles';
import {subscribe} from '../../lit/subscription-controller';
import {ParsedChangeInfo} from '../../../types/types';
import {repeat} from 'lit/directives/repeat.js';
import {GrCommentThread} from '../../shared/gr-comment-thread/gr-comment-thread';
import {resolve} from '../../../models/dependency';
import {changeModelToken} from '../../../models/change/change-model';
import {userModelToken} from '../../../models/user/user-model';
import {specialFilePathCompare} from '../../../utils/path-list-util';

enum SortDropdownState {
  TIMESTAMP = 'Latest timestamp',
  FILES = 'Files',
}

export const __testOnly_SortDropdownState = SortDropdownState;

/**
 * Order as follows:
 * - Patchset level threads (descending based on patchset number)
 * - unresolved
 * - comments with drafts
 * - comments without drafts
 * - resolved
 * - comments with drafts
 * - comments without drafts
 * - File name
 * - Line number
 * - Unresolved (descending based on patchset number)
 * - comments with drafts
 * - comments without drafts
 * - Resolved (descending based on patchset number)
 * - comments with drafts
 * - comments without drafts
 */
export function compareThreads(
  c1: CommentThread,
  c2: CommentThread,
  byTimestamp = false
) {
  if (byTimestamp) {
    const c1Time = lastUpdated(c1)?.getTime() ?? 0;
    const c2Time = lastUpdated(c2)?.getTime() ?? 0;
    const timeDiff = c2Time - c1Time;
    if (timeDiff !== 0) return c2Time - c1Time;
  }

  if (c1.path !== c2.path) {
    // '/PATCHSET' will not come before '/COMMIT' when sorting
    // alphabetically so move it to the front explicitly
    if (c1.path === SpecialFilePath.PATCHSET_LEVEL_COMMENTS) {
      return -1;
    }
    if (c2.path === SpecialFilePath.PATCHSET_LEVEL_COMMENTS) {
      return 1;
    }
    return specialFilePathCompare(c1.path, c2.path);
  }

  // Convert 'FILE' and 'LOST' to undefined.
  const line1 = typeof c1.line === 'number' ? c1.line : undefined;
  const line2 = typeof c2.line === 'number' ? c2.line : undefined;
  if (line1 !== line2) {
    // one of them is a FILE/LOST comment, show first
    if (line1 === undefined) return -1;
    if (line2 === undefined) return 1;
    // Lower line numbers first.
    return line1 < line2 ? -1 : 1;
  }

  if (c1.patchNum !== c2.patchNum) {
    // `patchNum` should be required, but show undefined first.
    if (c1.patchNum === undefined) return -1;
    if (c2.patchNum === undefined) return 1;
    // Higher patchset numbers first.
    return c1.patchNum > c2.patchNum ? -1 : 1;
  }

  // Sorting should not be based on the thread being unresolved or being a draft
  // thread, because that would be a surprising re-sort when the thread changes
  // state.

  const c1Time = lastUpdated(c1)?.getTime() ?? 0;
  const c2Time = lastUpdated(c2)?.getTime() ?? 0;
  if (c2Time !== c1Time) {
    // Newer comments first.
    return c2Time - c1Time;
  }

  return 0;
}

@customElement('gr-thread-list')
export class GrThreadList extends LitElement {
  @queryAll('gr-comment-thread')
  threadElements?: NodeListOf<GrCommentThread>;

  /**
   * Raw list of threads for the component to show.
   *
   * ATTENTION! this.threads should never be used directly within the component.
   *
   * Either use getAllThreads(), which applies filters that are inherent to what
   * the component is supposed to render,
   * e.g. onlyShowRobotCommentsWithHumanReply.
   *
   * Or use getDisplayedThreads(), which applies the currently selected filters
   * on top.
   */
  @property({type: Array})
  threads: CommentThread[] = [];

  @property({type: Boolean, attribute: 'show-comment-context'})
  showCommentContext = false;

  /** Along with `draftsOnly` is the currently selected filter. */
  @property({type: Boolean, attribute: 'unresolved-only'})
  unresolvedOnly = false;

  @property({
    type: Boolean,
    attribute: 'only-show-robot-comments-with-human-reply',
  })
  onlyShowRobotCommentsWithHumanReply = false;

  @property({type: Boolean, attribute: 'hide-dropdown'})
  hideDropdown = false;

  @property({type: Object, attribute: 'comment-tab-state'})
  commentTabState?: TabState;

  @property({type: String, attribute: 'scroll-comment-id'})
  scrollCommentId?: UrlEncodedCommentId;

  /**
   * Optional context information when threads are being displayed for a
   * specific change message. That influences which comments are expanded or
   * collapsed by default.
   */
  @property({type: String, attribute: 'message-id'})
  messageId?: ChangeMessageId;

  @state()
  changeNum?: NumericChangeId;

  @state()
  change?: ParsedChangeInfo;

  @state()
  account?: AccountDetailInfo;

  @state()
  selectedAuthors: AccountInfo[] = [];

  @state()
  sortDropdownValue: SortDropdownState = SortDropdownState.TIMESTAMP;

  /** Along with `unresolvedOnly` is the currently selected filter. */
  @state()
  draftsOnly = false;

  @state()
  mentionsOnly = false;

  private readonly getChangeModel = resolve(this, changeModelToken);

  private readonly getUserModel = resolve(this, userModelToken);

  constructor() {
    super();
    subscribe(
      this,
      () => this.getChangeModel().changeNum$,
      x => (this.changeNum = x)
    );
    subscribe(
      this,
      () => this.getChangeModel().change$,
      x => (this.change = x)
    );
    subscribe(
      this,
      () => this.getUserModel().account$,
      x => (this.account = x)
    );
  }

  override willUpdate(changed: PropertyValues) {
    if (changed.has('commentTabState')) this.onCommentTabStateUpdate();
    if (changed.has('scrollCommentId')) this.onScrollCommentIdUpdate();
  }

  private onCommentTabStateUpdate() {
    switch (this.commentTabState?.commentTab) {
      case CommentTabState.MENTIONS:
        this.handleOnlyMentions();
        break;
      case CommentTabState.UNRESOLVED:
        this.handleOnlyUnresolved();
        break;
      case CommentTabState.DRAFTS:
        this.handleOnlyDrafts();
        break;
      case CommentTabState.SHOW_ALL:
        this.handleAllComments();
        break;
    }
  }

  /**
   * When user wants to scroll to a comment, render all comments so that the
   * appropriate comment can be scrolled into view.
   */
  private onScrollCommentIdUpdate() {
    if (this.scrollCommentId) this.handleAllComments();
  }

  static override get styles() {
    return [
      sharedStyles,
      css`
        #threads {
          display: block;
        }
        gr-comment-thread {
          display: block;
          margin-bottom: var(--spacing-m);
        }
        .header {
          align-items: center;
          background-color: var(--background-color-primary);
          border-bottom: 1px solid var(--border-color);
          border-top: 1px solid var(--border-color);
          display: flex;
          justify-content: left;
          padding: var(--spacing-s) var(--spacing-l);
        }
        .draftsOnly:not(.unresolvedOnly) gr-comment-thread[has-draft],
        .unresolvedOnly:not(.draftsOnly) gr-comment-thread[unresolved],
        .draftsOnly.unresolvedOnly gr-comment-thread[has-draft][unresolved] {
          display: block;
        }
        .thread-separator {
          border-top: 1px solid var(--border-color);
          margin-top: var(--spacing-xl);
        }
        .show-resolved-comments {
          box-shadow: none;
          padding-left: var(--spacing-m);
        }
        .partypopper {
          margin-right: var(--spacing-s);
        }
        gr-dropdown-list {
          --trigger-style-text-color: var(--primary-text-color);
          --trigger-style-font-family: var(--font-family);
        }
        .filter-text,
        .sort-text,
        .author-text {
          margin-right: var(--spacing-s);
          color: var(--deemphasized-text-color);
        }
        .author-text {
          margin-left: var(--spacing-m);
        }
        gr-account-label {
          --account-max-length: 120px;
          display: inline-block;
          user-select: none;
          --label-border-radius: 8px;
          margin: 0 var(--spacing-xs);
          padding: var(--spacing-xs) var(--spacing-m);
          line-height: var(--line-height-normal);
          cursor: pointer;
        }
        gr-account-label:focus {
          outline: none;
        }
        gr-account-label:hover,
        gr-account-label:hover {
          box-shadow: var(--elevation-level-1);
          cursor: pointer;
        }
      `,
    ];
  }

  override render() {
    return html`
      ${this.renderDropdown()}
      <div id="threads" part="threads">
        ${this.renderEmptyThreadsMessage()} ${this.renderCommentThreads()}
      </div>
    `;
  }

  private renderDropdown() {
    if (this.hideDropdown) return;
    return html`
      <div class="header">
        <span class="sort-text">Sort By:</span>
        <gr-dropdown-list
          id="sortDropdown"
          .value=${this.sortDropdownValue}
          @value-change=${(e: ValueChangedEvent<SortDropdownState>) =>
            (this.sortDropdownValue = e.detail.value)}
          .items=${this.getSortDropdownEntries()}
        >
        </gr-dropdown-list>
        <span class="separator"></span>
        <span class="filter-text">Filter By:</span>
        <gr-dropdown-list
          id="filterDropdown"
          .value=${this.getCommentsDropdownValue()}
          @value-change=${this.handleCommentsDropdownValueChange}
          .items=${this.getCommentsDropdownEntries()}
        >
        </gr-dropdown-list>
        ${this.renderAuthorChips()}
      </div>
    `;
  }

  private renderEmptyThreadsMessage() {
    const threads = this.getAllThreads();
    const threadsEmpty = threads.length === 0;
    const displayedEmpty = this.getDisplayedThreads().length === 0;
    if (!displayedEmpty) return;
    const showPopper = this.unresolvedOnly && !threadsEmpty;
    const popper = html`<span class="partypopper">&#x1F389;</span>`;
    const showButton = this.unresolvedOnly && !threadsEmpty;
    const button = html`
      <gr-button
        class="show-resolved-comments"
        link
        @click=${this.handleAllComments}
        >Show ${pluralize(threads.length, 'resolved comment')}</gr-button
      >
    `;
    return html`
      <div>
        <span>
          ${showPopper ? popper : undefined}
          ${threadsEmpty ? 'No comments' : 'No unresolved comments'}
          ${showButton ? button : undefined}
        </span>
      </div>
    `;
  }

  private renderCommentThreads() {
    const threads = this.getDisplayedThreads();
    return repeat(
      threads,
      thread => thread.rootId,
      (thread, index) => {
        const isFirst =
          index === 0 || threads[index - 1].path !== threads[index].path;
        const separator =
          index !== 0 && isFirst
            ? html`<div class="thread-separator"></div>`
            : undefined;
        const commentThread = this.renderCommentThread(thread, isFirst);
        return html`${separator}${commentThread}`;
      }
    );
  }

  private renderCommentThread(thread: CommentThread, isFirst: boolean) {
    return html`
      <gr-comment-thread
        .thread=${thread}
        show-file-path
        ?show-ported-comment=${thread.ported}
        ?show-comment-context=${this.showCommentContext}
        ?show-file-name=${isFirst}
        .messageId=${this.messageId}
        ?should-scroll-into-view=${thread.rootId === this.scrollCommentId}
        @comment-thread-editing-changed=${() => {
          this.requestUpdate();
        }}
      ></gr-comment-thread>
    `;
  }

  private renderAuthorChips() {
    const authors = getCommentAuthors(this.getDisplayedThreads(), this.account);
    if (authors.length === 0) return;
    return html`<span class="author-text">From:</span>${authors.map(author =>
        this.renderAccountChip(author)
      )}`;
  }

  private renderAccountChip(account: AccountInfo) {
    const selected = this.selectedAuthors.some(
      a => a._account_id === account._account_id
    );
    return html`
      <gr-account-label
        .account=${account}
        @click=${this.handleAccountClicked}
        selectionChipStyle
        noStatusIcons
        ?selected=${selected}
      ></gr-account-label>
    `;
  }

  private getCommentsDropdownValue() {
    if (this.mentionsOnly) return CommentTabState.MENTIONS;
    if (this.draftsOnly) return CommentTabState.DRAFTS;
    if (this.unresolvedOnly) return CommentTabState.UNRESOLVED;
    return CommentTabState.SHOW_ALL;
  }

  private getSortDropdownEntries() {
    return [
      {text: SortDropdownState.FILES, value: SortDropdownState.FILES},
      {text: SortDropdownState.TIMESTAMP, value: SortDropdownState.TIMESTAMP},
    ];
  }

  // private, but visible for testing
  getCommentsDropdownEntries() {
    const items: DropdownItem[] = [];
    const threads = this.getAllThreads();
    items.push({
      text: `Unresolved (${threads.filter(isUnresolved).length})`,
      value: CommentTabState.UNRESOLVED,
    });
    if (this.account) {
      items.push({
        text: `Mentions (${getMentionedThreads(threads, this.account).length})`,
        value: CommentTabState.MENTIONS,
      });
      items.push({
        text: `Drafts (${threads.filter(isDraftThread).length})`,
        value: CommentTabState.DRAFTS,
      });
    }
    items.push({
      text: `All (${threads.length})`,
      value: CommentTabState.SHOW_ALL,
    });
    return items;
  }

  private handleAccountClicked(e: MouseEvent) {
    const account = (e.target as GrAccountChip).account;
    assertIsDefined(account, 'account');
    const predicate = (a: AccountInfo) => a._account_id === account._account_id;
    const found = this.selectedAuthors.find(predicate);
    if (found) {
      this.selectedAuthors = this.selectedAuthors.filter(a => !predicate(a));
    } else {
      this.selectedAuthors = [...this.selectedAuthors, account];
    }
  }

  // private, but visible for testing
  handleCommentsDropdownValueChange(e: ValueChangedEvent<CommentTabState>) {
    const value = e.detail.value;
    switch (value) {
      case CommentTabState.UNRESOLVED:
        this.handleOnlyUnresolved();
        break;
      case CommentTabState.MENTIONS:
        this.handleOnlyMentions();
        break;
      case CommentTabState.DRAFTS:
        this.handleOnlyDrafts();
        break;
      default:
        this.handleAllComments();
    }
  }

  /**
   * Returns all threads that the list may show.
   */
  // private, but visible for testing
  getAllThreads() {
    return this.threads.filter(
      t =>
        !this.onlyShowRobotCommentsWithHumanReply ||
        !isRobotThread(t) ||
        hasHumanReply(t)
    );
  }

  /**
   * Returns all threads that are currently shown in the list, respecting the
   * currently selected filter.
   */
  // private, but visible for testing
  getDisplayedThreads() {
    const byTimestamp =
      this.sortDropdownValue === SortDropdownState.TIMESTAMP &&
      !this.hideDropdown;
    return this.getAllThreads()
      .sort((t1, t2) => compareThreads(t1, t2, byTimestamp))
      .filter(t => this.shouldShowThread(t));
  }

  private isASelectedAuthor(account?: AccountInfo) {
    if (!account) return false;
    return this.selectedAuthors.some(
      author => account._account_id === author._account_id
    );
  }

  private shouldShowThread(thread: CommentThread) {
    // Never make a thread disappear while the user is editing it.
    assertIsDefined(thread.rootId, 'thread.rootId');
    const el = this.queryThreadElement(thread.rootId);
    if (el?.editing) return true;

    if (this.selectedAuthors.length > 0) {
      const hasACommentFromASelectedAuthor = thread.comments.some(
        c =>
          (isDraft(c) && this.isASelectedAuthor(this.account)) ||
          this.isASelectedAuthor(c.author)
      );
      if (!hasACommentFromASelectedAuthor) return false;
    }

    // This is probably redundant, because getAllThreads() filters this out.
    if (this.onlyShowRobotCommentsWithHumanReply) {
      if (isRobotThread(thread) && !hasHumanReply(thread)) return false;
    }

    if (this.mentionsOnly && !isMentionedThread(thread, this.account))
      return false;

    if (this.draftsOnly && !isDraftThread(thread)) return false;
    if (this.unresolvedOnly && !isUnresolved(thread)) return false;

    return true;
  }

  private handleOnlyUnresolved() {
    this.unresolvedOnly = true;
    this.draftsOnly = false;
    this.mentionsOnly = false;
  }

  private handleOnlyMentions() {
    this.mentionsOnly = true;
    this.unresolvedOnly = true;
    this.draftsOnly = false;
  }

  private handleOnlyDrafts() {
    this.draftsOnly = true;
    this.unresolvedOnly = false;
    this.mentionsOnly = false;
  }

  private handleAllComments() {
    this.draftsOnly = false;
    this.unresolvedOnly = false;
    this.mentionsOnly = false;
  }

  private queryThreadElement(rootId: string): GrCommentThread | undefined {
    const els = [...(this.threadElements ?? [])] as GrCommentThread[];
    return els.find(el => el.rootId === rootId);
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-thread-list': GrThreadList;
  }
}
