/**
 * @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 '../../../scripts/bundled-polymer.js';

import '@polymer/paper-toggle-button/paper-toggle-button.js';
import '../../../styles/shared-styles.js';
import '../../shared/gr-comment-thread/gr-comment-thread.js';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-thread-list_html.js';
import {util} from '../../../scripts/util.js';

import {NO_THREADS_MSG} from '../../../constants/messages.js';

/**
 * Fired when a comment is saved or deleted
 *
 * @event thread-list-modified
 * @extends Polymer.Element
 */
class GrThreadList extends GestureEventListeners(
    LegacyElementMixin(
        PolymerElement)) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-thread-list'; }

  static get properties() {
    return {
      /** @type {?} */
      change: Object,
      threads: Array,
      changeNum: String,
      loggedIn: Boolean,
      _sortedThreads: {
        type: Array,
      },
      _filteredThreads: {
        type: Array,
        computed: '_computeFilteredThreads(_sortedThreads, ' +
          '_unresolvedOnly, _draftsOnly,' +
          'onlyShowRobotCommentsWithHumanReply)',
      },
      _unresolvedOnly: {
        type: Boolean,
        value: false,
      },
      _draftsOnly: {
        type: Boolean,
        value: false,
      },
      /* Boolean properties used must default to false if passed as attribute
      by the parent */
      onlyShowRobotCommentsWithHumanReply: {
        type: Boolean,
        value: false,
      },
      hideToggleButtons: {
        type: Boolean,
        value: false,
      },
      emptyThreadMsg: {
        type: String,
        value: NO_THREADS_MSG,
      },
    };
  }

  static get observers() { return ['_computeSortedThreads(threads.*)']; }

  _computeShowDraftToggle(loggedIn) {
    return loggedIn ? 'show' : '';
  }

  /**
   * Order as follows:
   *  - Unresolved threads with drafts (reverse chronological)
   *  - Unresolved threads without drafts (reverse chronological)
   *  - Resolved threads with drafts (reverse chronological)
   *  - Resolved threads without drafts (reverse chronological)
   *
   * @param {!Object} changeRecord
   */
  _computeSortedThreads(changeRecord) {
    const threads = changeRecord.base;
    if (!threads) { return []; }
    this._updateSortedThreads(threads);
  }

  // TODO(taoalpha): should allow only sort once during initialization
  // to avoid flickering
  _updateSortedThreads(threads) {
    this._sortedThreads =
        threads.map(this._getThreadWithSortInfo).sort((c1, c2) => {
          // threads will be sorted by:
          // - unresolved first
          // - with drafts
          // - file path
          // - line
          // - updated time
          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; }
          }

          // TODO: Update here once we introduce patchset level comments
          // they may not have or have a special line or path attribute

          if (c1.thread.path !== c2.thread.path) {
            return c1.thread.path.localeCompare(c2.thread.path);
          }

          // File level comments (no `line` property)
          // should always show before any lines
          if ([c1, c2].some(c => c.thread.line === undefined)) {
            if (!c1.thread.line) { return -1; }
            if (!c2.thread.line) { return 1; }
          } else if (c1.thread.line !== c2.thread.line) {
            return c1.thread.line - c2.thread.line;
          }

          const c1Date = c1.__date || util.parseDate(c1.updated);
          const c2Date = c2.__date || util.parseDate(c2.updated);
          const dateCompare = c2Date - c1Date;
          if (dateCompare === 0 && (!c1.id || !c1.id.localeCompare)) {
            return 0;
          }
          return dateCompare ? dateCompare : c1.id.localeCompare(c2.id);
        });
  }

  _computeFilteredThreads(sortedThreads, unresolvedOnly, draftsOnly,
      onlyShowRobotCommentsWithHumanReply) {
    // Polymer 2: check for undefined
    if ([
      sortedThreads,
      unresolvedOnly,
      draftsOnly,
      onlyShowRobotCommentsWithHumanReply,
    ].some(arg => arg === undefined)) {
      return undefined;
    }

    return sortedThreads.filter(c => {
      if (draftsOnly) {
        return c.hasDraft;
      } else if (unresolvedOnly) {
        return c.unresolved;
      } else {
        const comments = c && c.thread && c.thread.comments;
        let robotComment = false;
        let humanReplyToRobotComment = false;
        comments.forEach(comment => {
          if (comment.robot_id) {
            robotComment = true;
          } else if (robotComment) {
            // Robot comment exists and human comment exists after it
            humanReplyToRobotComment = true;
          }
        });
        if (robotComment && onlyShowRobotCommentsWithHumanReply) {
          return humanReplyToRobotComment;
        }
        return c;
      }
    }).map(threadInfo => threadInfo.thread);
  }

  _getThreadWithSortInfo(thread) {
    const lastComment = thread.comments[thread.comments.length - 1] || {};

    const lastNonDraftComment =
        (lastComment.__draft && thread.comments.length > 1) ?
          thread.comments[thread.comments.length - 2] :
          lastComment;

    return {
      thread,
      // Use the unresolved bit for the last non draft comment. This is what
      // anybody other than the current user would see.
      unresolved: !!lastNonDraftComment.unresolved,
      hasDraft: !!lastComment.__draft,
      updated: lastComment.updated || lastComment.__date,
    };
  }

  removeThread(rootId) {
    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) {
    this.removeThread(e.detail.rootId);
  }

  _handleCommentsChanged(e) {
    this.dispatchEvent(new CustomEvent('thread-list-modified',
        {detail: {rootId: e.detail.rootId, path: e.detail.path}}));
  }

  _isOnParent(side) {
    return !!side;
  }

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

customElements.define(GrThreadList.is, GrThreadList);
