/**
 * @license
 * Copyright (C) 2018 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 '../../../styles/shared-styles';
import '../../shared/gr-comment-thread/gr-comment-thread';
import '../../shared/gr-dropdown-list/gr-dropdown-list';

import {flush} from '@polymer/polymer/lib/legacy/polymer.dom';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-thread-list_html';
import {parseDate} from '../../../utils/date-util';

import {CommentSide, SpecialFilePath} from '../../../constants/constants';
import {computed, customElement, observe, property} from '@polymer/decorators';
import {
  PolymerSpliceChange,
  PolymerDeepPropertyChange,
} from '@polymer/polymer/interfaces';
import {AccountInfo, ChangeInfo} from '../../../types/common';
import {
  CommentThread,
  isDraft,
  isUnresolved,
  isDraftThread,
  isRobotThread,
  hasHumanReply,
  getCommentAuthors,
} from '../../../utils/comment-util';
import {pluralize} from '../../../utils/string-util';
import {fireThreadListModifiedEvent} from '../../../utils/event-util';
import {assertIsDefined, assertNever} from '../../../utils/common-util';
import {CommentTabState} from '../../../types/events';
import {DropdownItem} from '../../shared/gr-dropdown-list/gr-dropdown-list';
import {GrAccountChip} from '../../shared/gr-account-chip/gr-account-chip';

interface CommentThreadWithInfo {
  thread: CommentThread;
  hasRobotComment: boolean;
  hasHumanReplyToRobotComment: boolean;
  unresolved: boolean;
  isEditing: boolean;
  hasDraft: boolean;
  updated?: Date;
}

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

export const __testOnly_SortDropdownState = SortDropdownState;

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

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

  @property({type: Array})
  threads: CommentThread[] = [];

  @property({type: String})
  changeNum?: string;

  @property({type: Boolean})
  loggedIn?: boolean;

  @property({type: Array})
  _sortedThreads: CommentThread[] = [];

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

  @property({
    computed:
      '_computeDisplayedThreads(_sortedThreads.*, unresolvedOnly, ' +
      '_draftsOnly, onlyShowRobotCommentsWithHumanReply, selectedAuthors)',
    type: Array,
  })
  _displayedThreads: CommentThread[] = [];

  // thread-list is used in multiple places like the change log, hence
  // keeping the default to be false. When used in comments tab, it's
  // set as true.
  @property({type: Boolean})
  unresolvedOnly = false;

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

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

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

  @property({type: Object, observer: '_commentTabStateChange'})
  commentTabState?: CommentTabState;

  @property({type: Object})
  sortDropdownValue: SortDropdownState = SortDropdownState.TIMESTAMP;

  @property({type: Array, notify: true})
  selectedAuthors: AccountInfo[] = [];

  @computed('unresolvedOnly', '_draftsOnly')
  get commentsDropdownValue() {
    // set initial value and triggered when comment summary chips are clicked
    if (this._draftsOnly) return CommentTabState.DRAFTS;
    return this.unresolvedOnly
      ? CommentTabState.UNRESOLVED
      : CommentTabState.SHOW_ALL;
  }

  _showEmptyThreadsMessage(
    threads: CommentThread[],
    displayedThreads: CommentThread[],
    unresolvedOnly: boolean
  ) {
    if (!threads || !displayedThreads) return false;
    return !threads.length || (unresolvedOnly && !displayedThreads.length);
  }

  _computeEmptyThreadsMessage(threads: CommentThread[]) {
    return !threads.length ? 'No comments' : 'No unresolved comments';
  }

  _showPartyPopper(threads: CommentThread[]) {
    return !!threads.length;
  }

  _computeResolvedCommentsMessage(
    threads: CommentThread[],
    displayedThreads: CommentThread[],
    unresolvedOnly: boolean,
    onlyShowRobotCommentsWithHumanReply: boolean
  ) {
    if (onlyShowRobotCommentsWithHumanReply) {
      threads = this.filterRobotThreadsWithoutHumanReply(threads) ?? [];
    }
    if (unresolvedOnly && threads.length && !displayedThreads.length) {
      return `Show ${pluralize(threads.length, 'resolved comment')}`;
    }
    return '';
  }

  _showResolvedCommentsButton(
    threads: CommentThread[],
    displayedThreads: CommentThread[],
    unresolvedOnly: boolean
  ) {
    return unresolvedOnly && threads.length && !displayedThreads.length;
  }

  _handleResolvedCommentsMessageClick() {
    this.unresolvedOnly = !this.unresolvedOnly;
  }

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

  getCommentsDropdownEntires(threads: CommentThread[], loggedIn?: boolean) {
    const items: DropdownItem[] = [
      {
        text: `Unresolved (${this._countUnresolved(threads)})`,
        value: CommentTabState.UNRESOLVED,
      },
      {
        text: `All (${this._countAllThreads(threads)})`,
        value: CommentTabState.SHOW_ALL,
      },
    ];
    if (loggedIn)
      items.splice(1, 0, {
        text: `Drafts (${this._countDrafts(threads)})`,
        value: CommentTabState.DRAFTS,
      });
    return items;
  }

  getCommentAuthors(threads?: CommentThread[]) {
    return getCommentAuthors(threads);
  }

  handleAccountClicked(e: MouseEvent) {
    const account = (e.target as GrAccountChip).account;
    assertIsDefined(account, 'account');
    const index = this.selectedAuthors.findIndex(
      author => author._account_id === account._account_id
    );
    if (index === -1) this.push('selectedAuthors', account);
    else this.splice('selectedAuthors', index, 1);
    // re-assign so that isSelected template method is called
    this.selectedAuthors = [...this.selectedAuthors];
  }

  isSelected(author: AccountInfo, selectedAuthors: AccountInfo[]) {
    return selectedAuthors.some(a => a._account_id === author._account_id);
  }

  handleSortDropdownValueChange(e: CustomEvent) {
    this.sortDropdownValue = e.detail.value;
    /*
     * Ideally we would have updateSortedThreads observe on sortDropdownValue
     * but the method triggered re-render only when the length of threads
     * changes, hence keep the explicit resortThreads method
     */
    this.resortThreads(this.threads);
  }

  handleCommentsDropdownValueChange(e: CustomEvent) {
    const value = e.detail.value;
    if (value === CommentTabState.UNRESOLVED) this._handleOnlyUnresolved();
    else if (value === CommentTabState.DRAFTS) this._handleOnlyDrafts();
    else this._handleAllComments();
  }

  _compareThreads(c1: CommentThreadWithInfo, c2: CommentThreadWithInfo) {
    if (this.sortDropdownValue === SortDropdownState.TIMESTAMP) {
      if (c1.updated && c2.updated) return c1.updated > c2.updated ? -1 : 1;
    }

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

    // Patchset comments have no line/range associated with them
    if (c1.thread.line !== c2.thread.line) {
      if (!c1.thread.line || !c2.thread.line) {
        // one of them is a file level comment, show first
        return c1.thread.line ? 1 : -1;
      }
      return c1.thread.line < c2.thread.line ? -1 : 1;
    }

    if (c1.thread.patchNum !== c2.thread.patchNum) {
      if (!c1.thread.patchNum) return 1;
      if (!c2.thread.patchNum) return -1;
      // Threads left on Base when comparing Base vs X have patchNum = X
      // and CommentSide = PARENT
      // Threads left on 'edit' have patchNum set as latestPatchNum
      return c1.thread.patchNum > c2.thread.patchNum ? -1 : 1;
    }

    if (c2.unresolved !== c1.unresolved) {
      if (!c1.unresolved) return 1;
      if (!c2.unresolved) return -1;
    }

    if (c2.hasDraft !== c1.hasDraft) {
      if (!c1.hasDraft) return 1;
      if (!c2.hasDraft) return -1;
    }

    if (c2.updated !== c1.updated) {
      if (!c1.updated) return 1;
      if (!c2.updated) return -1;
      return c2.updated.getTime() - c1.updated.getTime();
    }

    if (c2.thread.rootId !== c1.thread.rootId) {
      if (!c1.thread.rootId) return 1;
      if (!c2.thread.rootId) return -1;
      return c1.thread.rootId.localeCompare(c2.thread.rootId);
    }

    return 0;
  }

  resortThreads(threads: CommentThread[]) {
    const threadsWithInfo = threads.map(thread =>
      this._getThreadWithStatusInfo(thread)
    );
    this._sortedThreads = threadsWithInfo
      .sort((t1, t2) => this._compareThreads(t1, t2))
      .map(threadInfo => threadInfo.thread);
  }

  /**
   * Observer on threads and update _sortedThreads when needed.
   * 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
   *
   * @param threads
   * @param spliceRecord
   */
  @observe('threads', 'threads.splices')
  _updateSortedThreads(
    threads: CommentThread[],
    _: PolymerSpliceChange<CommentThread[]>
  ) {
    if (!threads || threads.length === 0) {
      this._sortedThreads = [];
      this._displayedThreads = [];
      return;
    }
    // We only want to sort on thread additions / removals to avoid
    // re-rendering on modifications (add new reply / edit draft etc.).
    // https://polymer-library.polymer-project.org/3.0/docs/devguide/observers#array-observation
    // TODO(TS): We have removed a buggy check of the splices here. A splice
    // with addedCount > 0 or removed.length > 0 should also cause re-sorting
    // and re-rendering, but apparently spliceRecord is always undefined for
    // whatever reason.
    if (this._sortedThreads.length === threads.length) {
      // Instead of replacing the _sortedThreads which will trigger a re-render,
      // we override all threads inside of it.

      for (const thread of threads) {
        const idxInSortedThreads = this._sortedThreads.findIndex(
          t => t.rootId === thread.rootId
        );
        this.set(`_sortedThreads.${idxInSortedThreads}`, {...thread});
      }
      return;
    }

    this.resortThreads(threads);
  }

  _computeDisplayedThreads(
    sortedThreadsRecord?: PolymerDeepPropertyChange<
      CommentThread[],
      CommentThread[]
    >,
    unresolvedOnly?: boolean,
    draftsOnly?: boolean,
    onlyShowRobotCommentsWithHumanReply?: boolean,
    selectedAuthors?: AccountInfo[]
  ) {
    if (!sortedThreadsRecord || !sortedThreadsRecord.base) return [];
    return sortedThreadsRecord.base.filter(t =>
      this._shouldShowThread(
        t,
        unresolvedOnly,
        draftsOnly,
        onlyShowRobotCommentsWithHumanReply,
        selectedAuthors
      )
    );
  }

  _isFirstThreadWithFileName(
    displayedThreads: CommentThread[],
    thread: CommentThread,
    unresolvedOnly?: boolean,
    draftsOnly?: boolean,
    onlyShowRobotCommentsWithHumanReply?: boolean,
    selectedAuthors?: AccountInfo[]
  ) {
    const threads = displayedThreads.filter(t =>
      this._shouldShowThread(
        t,
        unresolvedOnly,
        draftsOnly,
        onlyShowRobotCommentsWithHumanReply,
        selectedAuthors
      )
    );
    const index = threads.findIndex(t => t.rootId === thread.rootId);
    if (index === -1) {
      return false;
    }
    return index === 0 || threads[index - 1].path !== threads[index].path;
  }

  _shouldRenderSeparator(
    displayedThreads: CommentThread[],
    thread: CommentThread,
    unresolvedOnly?: boolean,
    draftsOnly?: boolean,
    onlyShowRobotCommentsWithHumanReply?: boolean,
    selectedAuthors?: AccountInfo[]
  ) {
    const threads = displayedThreads.filter(t =>
      this._shouldShowThread(
        t,
        unresolvedOnly,
        draftsOnly,
        onlyShowRobotCommentsWithHumanReply,
        selectedAuthors
      )
    );
    const index = threads.findIndex(t => t.rootId === thread.rootId);
    if (index === -1) {
      return false;
    }
    return (
      index > 0 &&
      this._isFirstThreadWithFileName(
        displayedThreads,
        thread,
        unresolvedOnly,
        draftsOnly,
        onlyShowRobotCommentsWithHumanReply,
        selectedAuthors
      )
    );
  }

  _shouldShowThread(
    thread: CommentThread,
    unresolvedOnly?: boolean,
    draftsOnly?: boolean,
    onlyShowRobotCommentsWithHumanReply?: boolean,
    selectedAuthors?: AccountInfo[]
  ) {
    if (
      [
        thread,
        unresolvedOnly,
        draftsOnly,
        onlyShowRobotCommentsWithHumanReply,
        selectedAuthors,
      ].includes(undefined)
    ) {
      return false;
    }

    if (selectedAuthors!.length) {
      if (
        !thread.comments.some(
          c =>
            c.author &&
            selectedAuthors!.some(
              author => c.author!._account_id === author._account_id
            )
        )
      ) {
        return false;
      }
    }

    if (
      !draftsOnly &&
      !unresolvedOnly &&
      !onlyShowRobotCommentsWithHumanReply
    ) {
      return true;
    }

    const threadInfo = this._getThreadWithStatusInfo(thread);

    if (threadInfo.isEditing) {
      return true;
    }

    if (
      threadInfo.hasRobotComment &&
      onlyShowRobotCommentsWithHumanReply &&
      !threadInfo.hasHumanReplyToRobotComment
    ) {
      return false;
    }

    let filtersCheck = true;
    if (draftsOnly && unresolvedOnly) {
      filtersCheck = threadInfo.hasDraft && threadInfo.unresolved;
    } else if (draftsOnly) {
      filtersCheck = threadInfo.hasDraft;
    } else if (unresolvedOnly) {
      filtersCheck = threadInfo.unresolved;
    }

    return filtersCheck;
  }

  _getThreadWithStatusInfo(thread: CommentThread): CommentThreadWithInfo {
    const comments = thread.comments;
    const lastComment = comments.length
      ? comments[comments.length - 1]
      : undefined;
    const hasRobotComment = isRobotThread(thread);
    const hasHumanReplyToRobotComment =
      hasRobotComment && hasHumanReply(thread);
    let updated = undefined;
    if (lastComment) {
      if (isDraft(lastComment)) updated = lastComment.__date;
      if (lastComment.updated) updated = parseDate(lastComment.updated);
    }

    return {
      thread,
      hasRobotComment,
      hasHumanReplyToRobotComment,
      unresolved: !!lastComment && !!lastComment.unresolved,
      isEditing: isDraft(lastComment) && !!lastComment.__editing,
      hasDraft: !!lastComment && isDraft(lastComment),
      updated,
    };
  }

  removeThread(rootId: string) {
    for (let i = 0; i < this.threads.length; i++) {
      if (this.threads[i].rootId === rootId) {
        this.splice('threads', i, 1);
        // Needed to ensure threads get re-rendered in the correct order.
        flush();
        return;
      }
    }
  }

  _handleThreadDiscard(e: CustomEvent) {
    this.removeThread(e.detail.rootId);
  }

  _handleCommentsChanged(e: CustomEvent) {
    fireThreadListModifiedEvent(this, e.detail.rootId, e.detail.path);
  }

  _isOnParent(side?: CommentSide) {
    // TODO(TS): That looks like a bug? CommentSide.REVISION will also be
    // classified as parent??
    return !!side;
  }

  _handleOnlyUnresolved() {
    this.unresolvedOnly = true;
    this._draftsOnly = false;
  }

  _handleOnlyDrafts() {
    this._draftsOnly = true;
    this.unresolvedOnly = false;
  }

  _handleAllComments() {
    this._draftsOnly = false;
    this.unresolvedOnly = false;
  }

  _showAllComments(draftsOnly?: boolean, unresolvedOnly?: boolean) {
    return !draftsOnly && !unresolvedOnly;
  }

  _countUnresolved(threads?: CommentThread[]) {
    return (
      this.filterRobotThreadsWithoutHumanReply(threads)?.filter(isUnresolved)
        .length ?? 0
    );
  }

  _countAllThreads(threads?: CommentThread[]) {
    return this.filterRobotThreadsWithoutHumanReply(threads)?.length ?? 0;
  }

  _countDrafts(threads?: CommentThread[]) {
    return (
      this.filterRobotThreadsWithoutHumanReply(threads)?.filter(isDraftThread)
        .length ?? 0
    );
  }

  filterRobotThreadsWithoutHumanReply(threads?: CommentThread[]) {
    return threads?.filter(t => !isRobotThread(t) || hasHumanReply(t));
  }

  _commentTabStateChange(
    newValue?: CommentTabState,
    oldValue?: CommentTabState
  ) {
    if (!newValue || newValue === oldValue) return;
    let focusTo: string | undefined;
    switch (newValue) {
      case CommentTabState.UNRESOLVED:
        this._handleOnlyUnresolved();
        // input is null because it's not rendered yet.
        focusTo = '#unresolvedRadio';
        break;
      case CommentTabState.DRAFTS:
        this._handleOnlyDrafts();
        focusTo = '#draftsRadio';
        break;
      case CommentTabState.SHOW_ALL:
        this._handleAllComments();
        focusTo = '#allRadio';
        break;
      default:
        assertNever(newValue, 'Unsupported preferred state');
    }
    const selector = focusTo;
    window.setTimeout(() => {
      const input = this.shadowRoot?.querySelector<HTMLInputElement>(selector);
      input?.focus();
    }, 0);
  }
}

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