/**
 * @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 '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import '../../shared/gr-comment-thread/gr-comment-thread.js';
import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
import '../gr-diff/gr-diff.js';
import '../gr-syntax-layer/gr-syntax-layer.js';
import {dom} 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-diff-host_html.js';
import {GrDiffBuilder} from '../gr-diff-builder/gr-diff-builder.js';
import {parseDate} from '../../../utils/date-util.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {DiffSide, rangesEqual} from '../gr-diff/gr-diff-utils.js';
import {appContext} from '../../../services/app-context.js';
import {getParentIndex, isMergeParent} from '../../../utils/patch-set-util.js';

const MSG_EMPTY_BLAME = 'No blame information for this diff.';

const EVENT_AGAINST_PARENT = 'diff-against-parent';
const EVENT_ZERO_REBASE = 'rebase-percent-zero';
const EVENT_NONZERO_REBASE = 'rebase-percent-nonzero';

const DiffViewMode = {
  SIDE_BY_SIDE: 'SIDE_BY_SIDE',
  UNIFIED: 'UNIFIED_DIFF',
};

/** @enum {string} */
const TimingLabel = {
  TOTAL: 'Diff Total Render',
  CONTENT: 'Diff Content Render',
  SYNTAX: 'Diff Syntax Render',
};

// Disable syntax highlighting if the overall diff is too large.
const SYNTAX_MAX_DIFF_LENGTH = 20000;

// If any line of the diff is more than the character limit, then disable
// syntax highlighting for the entire file.
const SYNTAX_MAX_LINE_LENGTH = 500;

// 120 lines is good enough threshold for full-sized window viewport
const NUM_OF_LINES_THRESHOLD_FOR_VIEWPORT = 120;

const WHITESPACE_IGNORE_NONE = 'IGNORE_NONE';

/**
 * @param {Object} diff
 * @return {boolean}
 */
function isImageDiff(diff) {
  if (!diff) { return false; }

  const isA = diff.meta_a &&
      diff.meta_a.content_type.startsWith('image/');
  const isB = diff.meta_b &&
      diff.meta_b.content_type.startsWith('image/');

  return !!(diff.binary && (isA || isB));
}

/**
 * Wrapper around gr-diff.
 *
 * Webcomponent fetching diffs and related data from restAPI and passing them
 * to the presentational gr-diff for rendering.
 *
 * @extends PolymerElement
 */
class GrDiffHost extends GestureEventListeners(
    LegacyElementMixin(
        PolymerElement)) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-diff-host'; }
  /**
   * Fired when the user selects a line.
   *
   * @event line-selected
   */

  /**
   * Fired if being logged in is required.
   *
   * @event show-auth-required
   */

  /**
   * Fired when a comment is saved or discarded
   *
   * @event diff-comments-modified
   */

  static get properties() {
    return {
      changeNum: String,
      noAutoRender: {
        type: Boolean,
        value: false,
      },
      /** @type {?} */
      patchRange: Object,
      /** @type {!Gerrit.FileRange} */
      file: Object,
      // TODO: deprecate path since that info is included in file
      path: String,
      prefs: {
        type: Object,
      },
      projectName: String,
      displayLine: {
        type: Boolean,
        value: false,
      },
      isImageDiff: {
        type: Boolean,
        computed: '_computeIsImageDiff(diff)',
        notify: true,
      },
      commitRange: Object,
      filesWeblinks: {
        type: Object,
        value() {
          return {};
        },
        notify: true,
      },
      hidden: {
        type: Boolean,
        reflectToAttribute: true,
      },
      noRenderOnPrefsChange: {
        type: Boolean,
        value: false,
      },
      comments: {
        type: Object,
        observer: '_commentsChanged',
      },
      lineWrapping: {
        type: Boolean,
        value: false,
      },
      viewMode: {
        type: String,
        value: DiffViewMode.SIDE_BY_SIDE,
      },

      /**
       * Special line number which should not be collapsed into a shared region.
       *
       * @type {{
       *  number: number,
       *  leftSide: {boolean}
       * }|null}
       */
      lineOfInterest: Object,

      /**
       * If the diff fails to load, show the failure message in the diff rather
       * than bubbling the error up to the whole page. This is useful for when
       * loading inline diffs because one diff failing need not mark the whole
       * page with a failure.
       */
      showLoadFailure: Boolean,

      isBlameLoaded: {
        type: Boolean,
        notify: true,
        computed: '_computeIsBlameLoaded(_blame)',
      },

      _loggedIn: {
        type: Boolean,
        value: false,
      },

      _loading: {
        type: Boolean,
        value: false,
      },

      /** @type {?string} */
      _errorMessage: {
        type: String,
        value: null,
      },

      /** @type {?Object} */
      _baseImage: Object,
      /** @type {?Object} */
      _revisionImage: Object,
      /**
       * This is a DiffInfo object.
       */
      diff: {
        type: Object,
        notify: true,
      },

      _fetchDiffPromise: {
        type: Object,
        value: null,
      },

      /** @type {?Object} */
      _blame: {
        type: Object,
        value: null,
      },

      /**
       * @type {!Array<!Gerrit.CoverageRange>}
       */
      _coverageRanges: {
        type: Array,
        value: () => [],
      },

      _loadedWhitespaceLevel: String,

      _parentIndex: {
        type: Number,
        computed: '_computeParentIndex(patchRange.*)',
      },

      _syntaxHighlightingEnabled: {
        type: Boolean,
        computed:
        '_isSyntaxHighlightingEnabled(prefs.*, diff)',
      },

      _layers: {
        type: Array,
        value: [],
      },
    };
  }

  static get observers() {
    return [
      '_whitespaceChanged(prefs.ignore_whitespace, _loadedWhitespaceLevel,' +
        ' noRenderOnPrefsChange)',
      '_syntaxHighlightingChanged(noRenderOnPrefsChange, prefs.*)',
    ];
  }

  constructor() {
    super();
    this.reporting = appContext.reportingService;
  }

  /** @override */
  created() {
    super.created();
    this.addEventListener(
        // These are named inconsistently for a reason:
        // The create-comment event is fired to indicate that we should
        // create a comment.
        // The comment-* events are just notifying that the comments did already
        // change in some way, and that we should update any models we may want
        // to keep in sync.
        'create-comment',
        e => this._handleCreateComment(e));
    this.addEventListener('comment-discard',
        e => this._handleCommentDiscard(e));
    this.addEventListener('comment-update',
        e => this._handleCommentUpdate(e));
    this.addEventListener('comment-save',
        e => this._handleCommentSave(e));
    this.addEventListener('render-start',
        () => this._handleRenderStart());
    this.addEventListener('render-content',
        () => this._handleRenderContent());
    this.addEventListener('normalize-range',
        event => this._handleNormalizeRange(event));
    this.addEventListener('diff-context-expanded',
        event => this._handleDiffContextExpanded(event));
  }

  /** @override */
  ready() {
    super.ready();
    if (this._canReload()) {
      this.reload();
    }
  }

  /** @override */
  attached() {
    super.attached();
    this._getLoggedIn().then(loggedIn => {
      this._loggedIn = loggedIn;
    });
  }

  /** @override */
  detached() {
    super.detached();
    this.clear();
  }

  /**
   * @param {boolean=} shouldReportMetric indicate a new Diff Page. This is a
   * signal to report metrics event that started on location change.
   * @return {!Promise}
   **/
  reload(shouldReportMetric) {
    this.clear();
    this._loading = true;
    this._errorMessage = null;
    const whitespaceLevel = this._getIgnoreWhitespace();

    const layers = [this.$.syntaxLayer];
    // Get layers from plugins (if any).
    for (const pluginLayer of this.$.jsAPI.getDiffLayers(
        this.path, this.changeNum, this.patchNum)) {
      layers.push(pluginLayer);
    }
    this._layers = layers;

    if (shouldReportMetric) {
      // We listen on render viewport only on DiffPage (on paramsChanged)
      this._listenToViewportRender();
    }

    this._coverageRanges = [];
    this._getCoverageData();
    const diffRequest = this._getDiff()
        .then(diff => {
          this._loadedWhitespaceLevel = whitespaceLevel;
          this._reportDiff(diff);
          return diff;
        })
        .catch(e => {
          this._handleGetDiffError(e);
          return null;
        });

    const assetRequest = diffRequest.then(diff => {
      // If the diff is null, then it's failed to load.
      if (!diff) { return null; }

      return this._loadDiffAssets(diff);
    });

    // Not waiting for coverage ranges intentionally as
    // plugin loading should not block the content rendering
    return Promise.all([diffRequest, assetRequest])
        .then(results => {
          const diff = results[0];
          if (!diff) {
            return Promise.resolve();
          }
          this.filesWeblinks = this._getFilesWeblinks(diff);
          return new Promise(resolve => {
            const callback = event => {
              const needsSyntaxHighlighting = event.detail &&
                    event.detail.contentRendered;
              if (needsSyntaxHighlighting) {
                this.reporting.time(TimingLabel.SYNTAX);
                this.$.syntaxLayer.process().finally(() => {
                  this.reporting.timeEnd(TimingLabel.SYNTAX);
                  this.reporting.timeEnd(TimingLabel.TOTAL);
                  resolve();
                });
              } else {
                this.reporting.timeEnd(TimingLabel.TOTAL);
                resolve();
              }
              this.removeEventListener('render', callback);
              if (shouldReportMetric) {
                // We report diffViewContentDisplayed only on reload caused
                // by params changed - expected only on Diff Page.
                this.reporting.diffViewContentDisplayed();
              }
            };
            this.addEventListener('render', callback);
            this.diff = diff;
          });
        })
        .catch(err => {
          console.warn('Error encountered loading diff:', err);
        })
        .then(() => { this._loading = false; });
  }

  clear() {
    this.$.jsAPI.disposeDiffLayers(this.path);
    this._layers = [];
  }

  _getCoverageData() {
    const {changeNum, path, patchRange: {basePatchNum, patchNum}} = this;
    this.$.jsAPI.getCoverageAnnotationApi().
        then(coverageAnnotationApi => {
          if (!coverageAnnotationApi) return;
          const provider = coverageAnnotationApi.getCoverageProvider();
          return provider(changeNum, path, basePatchNum, patchNum)
              .then(coverageRanges => {
                if (!coverageRanges ||
                  changeNum !== this.changeNum ||
                  path !== this.path ||
                  basePatchNum !== this.patchRange.basePatchNum ||
                  patchNum !== this.patchRange.patchNum) {
                  return;
                }

                const existingCoverageRanges = this._coverageRanges;
                this._coverageRanges = coverageRanges;

                // Notify with existing coverage ranges
                // in case there is some existing coverage data that needs to be removed
                existingCoverageRanges.forEach(range => {
                  coverageAnnotationApi.notify(
                      path,
                      range.code_range.start_line,
                      range.code_range.end_line,
                      range.side);
                });

                // Notify with new coverage data
                coverageRanges.forEach(range => {
                  coverageAnnotationApi.notify(
                      path,
                      range.code_range.start_line,
                      range.code_range.end_line,
                      range.side);
                });
              });
        })
        .catch(err => {
          console.warn('Loading coverage ranges failed: ', err);
        });
  }

  _getFilesWeblinks(diff) {
    if (!this.commitRange) {
      return {};
    }
    return {
      meta_a: GerritNav.getFileWebLinks(
          this.projectName, this.commitRange.baseCommit, this.path,
          {weblinks: diff && diff.meta_a && diff.meta_a.web_links}),
      meta_b: GerritNav.getFileWebLinks(
          this.projectName, this.commitRange.commit, this.path,
          {weblinks: diff && diff.meta_b && diff.meta_b.web_links}),
    };
  }

  /** Cancel any remaining diff builder rendering work. */
  cancel() {
    this.$.diff.cancel();
    this.$.syntaxLayer.cancel();
  }

  /** @return {!Array<!HTMLElement>} */
  getCursorStops() {
    return this.$.diff.getCursorStops();
  }

  /** @return {boolean} */
  isRangeSelected() {
    return this.$.diff.isRangeSelected();
  }

  createRangeComment() {
    return this.$.diff.createRangeComment();
  }

  toggleLeftDiff() {
    this.$.diff.toggleLeftDiff();
  }

  /**
   * Load and display blame information for the base of the diff.
   *
   * @return {Promise} A promise that resolves when blame finishes rendering.
   */
  loadBlame() {
    return this.$.restAPI.getBlame(this.changeNum, this.patchRange.patchNum,
        this.path, true)
        .then(blame => {
          if (!blame.length) {
            this.dispatchEvent(new CustomEvent('show-alert', {
              detail: {message: MSG_EMPTY_BLAME},
              composed: true, bubbles: true,
            }));
            return Promise.reject(MSG_EMPTY_BLAME);
          }

          this._blame = blame;
        });
  }

  /** Unload blame information for the diff. */
  clearBlame() {
    this._blame = null;
  }

  /**
   * The thread elements in this diff, in no particular order.
   *
   * @return {!Array<!HTMLElement>}
   */
  getThreadEls() {
    return Array.from(
        dom(this.$.diff).querySelectorAll('.comment-thread'));
  }

  /** @param {HTMLElement} el */
  addDraftAtLine(el) {
    this.$.diff.addDraftAtLine(el);
  }

  clearDiffContent() {
    this.$.diff.clearDiffContent();
  }

  expandAllContext() {
    this.$.diff.expandAllContext();
  }

  /** @return {!Promise} */
  _getLoggedIn() {
    return this.$.restAPI.getLoggedIn();
  }

  /** @return {boolean}} */
  _canReload() {
    return !!this.changeNum && !!this.patchRange && !!this.path &&
        !this.noAutoRender;
  }

  // TODO(milutin): Use rest-api with fetchCacheURL instead of this.
  prefetchDiff() {
    if (!!this.changeNum && !!this.patchRange && !!this.path
        && this._fetchDiffPromise === null) {
      this._fetchDiffPromise = this._getDiff();
    }
  }

  /** @return {!Promise<!Object>} */
  _getDiff() {
    if (this._fetchDiffPromise !== null) {
      const fetchDiffPromise = this._fetchDiffPromise;
      this._fetchDiffPromise = null;
      return fetchDiffPromise;
    }
    // Wrap the diff request in a new promise so that the error handler
    // rejects the promise, allowing the error to be handled in the .catch.
    return new Promise((resolve, reject) => {
      this.$.restAPI.getDiff(
          this.changeNum,
          this.patchRange.basePatchNum,
          this.patchRange.patchNum,
          this.path,
          this._getIgnoreWhitespace(),
          reject)
          .then(resolve);
    });
  }

  _handleGetDiffError(response) {
    // Loading the diff may respond with 409 if the file is too large. In this
    // case, use a toast error..
    if (response.status === 409) {
      this.dispatchEvent(new CustomEvent('server-error', {
        detail: {response},
        composed: true, bubbles: true,
      }));
      return;
    }

    if (this.showLoadFailure) {
      this._errorMessage = [
        'Encountered error when loading the diff:',
        response.status,
        response.statusText,
      ].join(' ');
      return;
    }

    this.dispatchEvent(new CustomEvent('page-error', {
      detail: {response},
      composed: true, bubbles: true,
    }));
  }

  /**
   * Report info about the diff response.
   */
  _reportDiff(diff) {
    if (!diff || !diff.content) {
      return;
    }

    // Count the delta lines stemming from normal deltas, and from
    // due_to_rebase deltas.
    let nonRebaseDelta = 0;
    let rebaseDelta = 0;
    diff.content.forEach(chunk => {
      if (chunk.ab) { return; }
      const deltaSize = Math.max(
          chunk.a ? chunk.a.length : 0, chunk.b ? chunk.b.length : 0);
      if (chunk.due_to_rebase) {
        rebaseDelta += deltaSize;
      } else {
        nonRebaseDelta += deltaSize;
      }
    });

    // Find the percent of the delta from due_to_rebase chunks rounded to two
    // digits. Diffs with no delta are considered 0%.
    const totalDelta = rebaseDelta + nonRebaseDelta;
    const percentRebaseDelta = !totalDelta ? 0 :
      Math.round(100 * rebaseDelta / totalDelta);

    // Report the due_to_rebase percentage in the "diff" category when
    // applicable.
    if (this.patchRange.basePatchNum === 'PARENT') {
      this.reporting.reportInteraction(EVENT_AGAINST_PARENT);
    } else if (percentRebaseDelta === 0) {
      this.reporting.reportInteraction(EVENT_ZERO_REBASE);
    } else {
      this.reporting.reportInteraction(EVENT_NONZERO_REBASE,
          {percentRebaseDelta});
    }
  }

  /**
   * @param {Object} diff
   * @return {!Promise}
   */
  _loadDiffAssets(diff) {
    if (isImageDiff(diff)) {
      return this._getImages(diff).then(images => {
        this._baseImage = images.baseImage;
        this._revisionImage = images.revisionImage;
      });
    } else {
      this._baseImage = null;
      this._revisionImage = null;
      return Promise.resolve();
    }
  }

  /**
   * @param {Object} diff
   * @return {boolean}
   */
  _computeIsImageDiff(diff) {
    return isImageDiff(diff);
  }

  _commentsChanged(newComments) {
    const allComments = [];
    for (const side of [GrDiffBuilder.Side.LEFT, GrDiffBuilder.Side.RIGHT]) {
      // This is needed by the threading.
      for (const comment of newComments[side]) {
        comment.__commentSide = side;
      }
      allComments.push(...newComments[side]);
    }
    // Currently, the only way this is ever changed here is when the initial
    // comments are loaded, so it's okay performance wise to clear the threads
    // and recreate them. If this changes in future, we might want to reuse
    // some DOM nodes here.
    this._clearThreads();
    const threads = this._createThreads(allComments);
    for (const thread of threads) {
      const threadEl = this._createThreadElement(thread);
      this._attachThreadElement(threadEl);
    }
  }

  _sortComments(comments) {
    return comments.slice(0).sort((a, b) => {
      if (b.__draft && !a.__draft ) { return -1; }
      if (a.__draft && !b.__draft ) { return 1; }
      return parseDate(a.updated) - parseDate(b.updated);
    });
  }

  /**
   * @param {!Array<!Object>} comments
   * @return {!Array<!Object>} Threads for the given comments.
   */
  _createThreads(comments) {
    const sortedComments = this._sortComments(comments);
    const threads = [];
    for (const comment of sortedComments) {
      // If the comment is in reply to another comment, find that comment's
      // thread and append to it.
      if (comment.in_reply_to) {
        const thread = threads.find(thread =>
          thread.comments.some(c => c.id === comment.in_reply_to));
        if (thread) {
          thread.comments.push(comment);
          continue;
        }
      }

      // Otherwise, this comment starts its own thread.
      const newThread = {
        start_datetime: comment.updated,
        comments: [comment],
        commentSide: comment.__commentSide,
        patchNum: comment.patch_set,
        rootId: comment.id || comment.__draftID,
        lineNum: comment.line,
        isOnParent: comment.side === 'PARENT',
      };
      if (comment.range) {
        newThread.range = {...comment.range};
      }
      threads.push(newThread);
    }
    return threads;
  }

  /**
   * @param {Object} blame
   * @return {boolean}
   */
  _computeIsBlameLoaded(blame) {
    return !!blame;
  }

  /**
   * @param {Object} diff
   * @return {!Promise}
   */
  _getImages(diff) {
    return this.$.restAPI.getImagesForDiff(this.changeNum, diff,
        this.patchRange);
  }

  /** @param {CustomEvent} e */
  _handleCreateComment(e) {
    const {lineNum, side, patchNum, isOnParent, range} = e.detail;
    const threadEl = this._getOrCreateThread(patchNum, lineNum, side, range,
        isOnParent);
    threadEl.addOrEditDraft(lineNum, range);

    this.reporting.recordDraftInteraction();
  }

  /**
   * Gets or creates a comment thread at a given location.
   * May provide a range, to get/create a range comment.
   *
   * @param {string} patchNum
   * @param {?number} lineNum
   * @param {string} commentSide
   * @param {Gerrit.Range|undefined} range
   * @param {boolean} isOnParent
   * @return {!Object}
   */
  _getOrCreateThread(patchNum, lineNum, commentSide, range, isOnParent) {
    let threadEl = this._getThreadEl(lineNum, commentSide, range);
    if (!threadEl) {
      threadEl = this._createThreadElement({
        comments: [],
        commentSide,
        patchNum,
        lineNum,
        range,
        isOnParent,
      });
      this._attachThreadElement(threadEl);
    }
    return threadEl;
  }

  _attachThreadElement(threadEl) {
    dom(this.$.diff).appendChild(threadEl);
  }

  _clearThreads() {
    for (const threadEl of this.getThreadEls()) {
      const parent = dom(threadEl).parentNode;
      dom(parent).removeChild(threadEl);
    }
  }

  _createThreadElement(thread) {
    const threadEl = document.createElement('gr-comment-thread');
    threadEl.className = 'comment-thread';
    threadEl.setAttribute('slot', `${thread.commentSide}-${thread.lineNum}`);
    threadEl.comments = thread.comments;
    threadEl.commentSide = thread.commentSide;
    threadEl.isOnParent = !!thread.isOnParent;
    threadEl.parentIndex = this._parentIndex;
    // Use path before renmaing when comment added on the left when comparing
    // two patch sets (not against base)
    if (this.file && this.file.basePath
        && thread.commentSide === GrDiffBuilder.Side.LEFT
        && !thread.isOnParent) {
      threadEl.path = this.file.basePath;
    } else {
      threadEl.path = this.path;
    }
    threadEl.changeNum = this.changeNum;
    threadEl.patchNum = thread.patchNum;
    threadEl.showPatchset = false;
    threadEl.lineNum = thread.lineNum;
    const rootIdChangedListener = changeEvent => {
      thread.rootId = changeEvent.detail.value;
    };
    threadEl.addEventListener('root-id-changed', rootIdChangedListener);
    threadEl.projectName = this.projectName;
    threadEl.range = thread.range;
    const threadDiscardListener = e => {
      const threadEl = /** @type {!Node} */ (e.currentTarget);

      const parent = dom(threadEl).parentNode;
      dom(parent).removeChild(threadEl);

      threadEl.removeEventListener('root-id-changed', rootIdChangedListener);
      threadEl.removeEventListener('thread-discard', threadDiscardListener);
    };
    threadEl.addEventListener('thread-discard', threadDiscardListener);
    return threadEl;
  }

  /**
   * Gets a comment thread element at a given location.
   * May provide a range, to get a range comment.
   *
   * @param {?number} lineNum
   * @param {string} commentSide
   * @param {!Gerrit.Range=} range
   * @return {?Node}
   */
  _getThreadEl(lineNum, commentSide, range = undefined) {
    let line;
    if (commentSide === GrDiffBuilder.Side.LEFT) {
      line = {beforeNumber: lineNum};
    } else if (commentSide === GrDiffBuilder.Side.RIGHT) {
      line = {afterNumber: lineNum};
    } else {
      throw new Error(`Unknown side: ${commentSide}`);
    }
    function matchesRange(threadEl) {
      const threadRange = /** @type {!Gerrit.Range} */(
        JSON.parse(threadEl.getAttribute('range')));
      return rangesEqual(threadRange, range);
    }

    const filteredThreadEls = this._filterThreadElsForLocation(
        this.getThreadEls(), line, commentSide).filter(matchesRange);
    return filteredThreadEls.length ? filteredThreadEls[0] : null;
  }

  /**
   * @param {!Array<!HTMLElement>} threadEls
   * @param {!{beforeNumber: (number|string|undefined|null),
   *           afterNumber: (number|string|undefined|null)}}
   *     lineInfo
   * @param {!DiffSide=} side The side (LEFT, RIGHT) for
   *     which to return the threads.
   * @return {!Array<!HTMLElement>} The thread elements matching the given
   *     location.
   */
  _filterThreadElsForLocation(threadEls, lineInfo, side) {
    function matchesLeftLine(threadEl) {
      return threadEl.getAttribute('comment-side') ==
          DiffSide.LEFT &&
          threadEl.getAttribute('line-num') == lineInfo.beforeNumber;
    }
    function matchesRightLine(threadEl) {
      return threadEl.getAttribute('comment-side') ==
          DiffSide.RIGHT &&
          threadEl.getAttribute('line-num') == lineInfo.afterNumber;
    }
    function matchesFileComment(threadEl) {
      return threadEl.getAttribute('comment-side') == side &&
            // line/range comments have 1-based line set, if line is falsy it's
            // a file comment
            !threadEl.getAttribute('line-num');
    }

    // Select the appropriate matchers for the desired side and line
    // If side is BOTH, we want both the left and right matcher.
    const matchers = [];
    if (side !== DiffSide.RIGHT) {
      matchers.push(matchesLeftLine);
    }
    if (side !== DiffSide.LEFT) {
      matchers.push(matchesRightLine);
    }
    if (lineInfo.afterNumber === 'FILE' ||
        lineInfo.beforeNumber === 'FILE') {
      matchers.push(matchesFileComment);
    }
    return threadEls.filter(threadEl =>
      matchers.some(matcher => matcher(threadEl)));
  }

  _getIgnoreWhitespace() {
    if (!this.prefs || !this.prefs.ignore_whitespace) {
      return WHITESPACE_IGNORE_NONE;
    }
    return this.prefs.ignore_whitespace;
  }

  _whitespaceChanged(
      preferredWhitespaceLevel, loadedWhitespaceLevel,
      noRenderOnPrefsChange) {
    // Polymer 2: check for undefined
    if ([
      preferredWhitespaceLevel,
      loadedWhitespaceLevel,
      noRenderOnPrefsChange,
    ].includes(undefined)) {
      return;
    }

    this._fetchDiffPromise = null;
    if (preferredWhitespaceLevel !== loadedWhitespaceLevel &&
        !noRenderOnPrefsChange) {
      this.reload();
    }
  }

  _syntaxHighlightingChanged(noRenderOnPrefsChange, prefsChangeRecord) {
    // Polymer 2: check for undefined
    if ([
      noRenderOnPrefsChange,
      prefsChangeRecord,
    ].includes(undefined)) {
      return;
    }

    if (prefsChangeRecord.path !== 'prefs.syntax_highlighting') {
      return;
    }

    if (!noRenderOnPrefsChange) {
      this.reload();
    }
  }

  /**
   * @param {Object} patchRangeRecord
   * @return {number|null}
   */
  _computeParentIndex(patchRangeRecord) {
    return isMergeParent(patchRangeRecord.base.basePatchNum) ?
      getParentIndex(patchRangeRecord.base.basePatchNum) : null;
  }

  _handleCommentSave(e) {
    const comment = e.detail.comment;
    const side = e.detail.comment.__commentSide;
    const idx = this._findDraftIndex(comment, side);
    this.set(['comments', side, idx], comment);
    this._handleCommentSaveOrDiscard();
  }

  _handleCommentDiscard(e) {
    const comment = e.detail.comment;
    this._removeComment(comment);
    this._handleCommentSaveOrDiscard();
  }

  /**
   * Closure annotation for Polymer.prototype.push is off. Submitted PR:
   * https://github.com/Polymer/polymer/pull/4776
   * but for not suppressing annotations.
   *
   * @suppress {checkTypes}
   */
  _handleCommentUpdate(e) {
    const comment = e.detail.comment;
    const side = e.detail.comment.__commentSide;
    let idx = this._findCommentIndex(comment, side);
    if (idx === -1) {
      idx = this._findDraftIndex(comment, side);
    }
    if (idx !== -1) { // Update draft or comment.
      this.set(['comments', side, idx], comment);
    } else { // Create new draft.
      this.push(['comments', side], comment);
    }
  }

  _handleCommentSaveOrDiscard() {
    this.dispatchEvent(new CustomEvent(
        'diff-comments-modified', {bubbles: true, composed: true}));
  }

  _removeComment(comment) {
    const side = comment.__commentSide;
    this._removeCommentFromSide(comment, side);
  }

  _removeCommentFromSide(comment, side) {
    let idx = this._findCommentIndex(comment, side);
    if (idx === -1) {
      idx = this._findDraftIndex(comment, side);
    }
    if (idx !== -1) {
      this.splice('comments.' + side, idx, 1);
    }
  }

  /** @return {number} */
  _findCommentIndex(comment, side) {
    if (!comment.id || !this.comments[side]) {
      return -1;
    }
    return this.comments[side].findIndex(item => item.id === comment.id);
  }

  /** @return {number} */
  _findDraftIndex(comment, side) {
    if (!comment.__draftID || !this.comments[side]) {
      return -1;
    }
    return this.comments[side].findIndex(
        item => item.__draftID === comment.__draftID);
  }

  _isSyntaxHighlightingEnabled(preferenceChangeRecord, diff) {
    if (!preferenceChangeRecord ||
        !preferenceChangeRecord.base ||
        !preferenceChangeRecord.base.syntax_highlighting ||
        !diff) {
      return false;
    }
    return !this._anyLineTooLong(diff) &&
        this.$.diff.getDiffLength(diff) <= SYNTAX_MAX_DIFF_LENGTH;
  }

  /**
   * @return {boolean} whether any of the lines in diff are longer
   * than SYNTAX_MAX_LINE_LENGTH.
   */
  _anyLineTooLong(diff) {
    if (!diff) return false;
    return diff.content.some(section => {
      const lines = section.ab ?
        section.ab :
        (section.a || []).concat(section.b || []);
      return lines.some(line => line.length >= SYNTAX_MAX_LINE_LENGTH);
    });
  }

  _listenToViewportRender() {
    const renderUpdateListener = start => {
      if (start > NUM_OF_LINES_THRESHOLD_FOR_VIEWPORT) {
        this.reporting.diffViewDisplayed();
        this.$.syntaxLayer.removeListener(renderUpdateListener);
      }
    };

    this.$.syntaxLayer.addListener(renderUpdateListener);
  }

  _handleRenderStart() {
    this.reporting.time(TimingLabel.TOTAL);
    this.reporting.time(TimingLabel.CONTENT);
  }

  _handleRenderContent() {
    this.reporting.timeEnd(TimingLabel.CONTENT);
  }

  _handleNormalizeRange(event) {
    this.reporting.reportInteraction('normalize-range',
        {
          side: event.detail.side,
          lineNum: event.detail.lineNum,
        });
  }

  _handleDiffContextExpanded(event) {
    this.reporting.reportInteraction(
        'diff-context-expanded', {numLines: event.detail.numLines}
    );
  }

  /**
   * Find the last chunk for the given side.
   *
   * @param {!Object} diff
   * @param {boolean} leftSide true if checking the base of the diff,
   *     false if testing the revision.
   * @return {Object|null} returns the chunk object or null if there was
   *     no chunk for that side.
   */
  _lastChunkForSide(diff, leftSide) {
    if (!diff.content.length) { return null; }

    let chunkIndex = diff.content.length;
    let chunk;

    // Walk backwards until we find a chunk for the given side.
    do {
      chunkIndex--;
      chunk = diff.content[chunkIndex];
    } while (
    // We haven't reached the beginning.
      chunkIndex >= 0 &&

        // The chunk doesn't have both sides.
        !chunk.ab &&

        // The chunk doesn't have the given side.
        ((leftSide && (!chunk.a || !chunk.a.length)) ||
         (!leftSide && (!chunk.b || !chunk.b.length))));

    // If we reached the beginning of the diff and failed to find a chunk
    // with the given side, return null.
    if (chunkIndex === -1) { return null; }

    return chunk;
  }

  /**
   * Check whether the specified side of the diff has a trailing newline.
   *
   * @param {!Object} diff
   * @param {boolean} leftSide true if checking the base of the diff,
   *     false if testing the revision.
   * @return {boolean|null} Return true if the side has a trailing newline.
   *     Return false if it doesn't. Return null if not applicable (for
   *     example, if the diff has no content on the specified side).
   */
  _hasTrailingNewlines(diff, leftSide) {
    const chunk = this._lastChunkForSide(diff, leftSide);
    if (!chunk) { return null; }
    let lines;
    if (chunk.ab) {
      lines = chunk.ab;
    } else {
      lines = leftSide ? chunk.a : chunk.b;
    }
    return lines[lines.length - 1] === '';
  }

  _showNewlineWarningLeft(diff) {
    return this._hasTrailingNewlines(diff, true) === false;
  }

  _showNewlineWarningRight(diff) {
    return this._hasTrailingNewlines(diff, false) === false;
  }
}

customElements.define(GrDiffHost.is, GrDiffHost);
