/**
 * @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 '../../../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 {
  AccountDetailInfo,
  AccountInfo,
  ChangeInfo,
  UrlEncodedCommentId,
} from '../../../types/common';
import {
  CommentThread,
  isDraft,
  isUnresolved,
  isDraftThread,
  isRobotThread,
  hasHumanReply,
  getCommentAuthors,
  computeId,
  UIComment,
} from '../../../utils/comment-util';
import {pluralize} from '../../../utils/string-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})
  hideDropdown = false;

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

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

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

  @property({type: Object})
  account?: AccountDetailInfo;

  @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;
  }

  @property({type: String})
  scrollCommentId?: UrlEncodedCommentId;

  _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[], account?: AccountDetailInfo) {
    return getCommentAuthors(threads, account);
  }

  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);
  }

  computeShouldScrollIntoView(
    comments: UIComment[],
    scrollCommentId?: UrlEncodedCommentId
  ) {
    const comment = comments?.[0];
    if (!comment) return false;
    return computeId(comment) === scrollCommentId;
  }

  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 &&
      !this.hideDropdown
    ) {
      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);
  }

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