/**
 * @license
 * Copyright (C) 2015 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 '../../../styles/shared-styles.js';
import '../../shared/gr-button/gr-button.js';
import '../gr-diff-builder/gr-diff-builder-element.js';
import '../gr-diff-highlight/gr-diff-highlight.js';
import '../gr-diff-selection/gr-diff-selection.js';
import '../gr-syntax-themes/gr-syntax-theme.js';
import '../gr-ranged-comment-themes/gr-ranged-comment-theme.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {htmlTemplate} from './gr-diff_html.js';
import {PatchSetBehavior} from '../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.js';
import {GrDiffLine} from './gr-diff-line.js';
import {DiffSide, rangesEqual} from './gr-diff-utils.js';
import {getHiddenScroll} from '../../../scripts/hiddenscroll.js';

const ERR_COMMENT_ON_EDIT = 'You cannot comment on an edit.';
const ERR_COMMENT_ON_EDIT_BASE = 'You cannot comment on the base patch set ' +
    'of an edit.';
const ERR_INVALID_LINE = 'Invalid line number: ';

const NO_NEWLINE_BASE = 'No newline at end of base file.';
const NO_NEWLINE_REVISION = 'No newline at end of revision file.';

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

const LARGE_DIFF_THRESHOLD_LINES = 10000;
const FULL_CONTEXT = -1;
const LIMITED_CONTEXT = 10;

function isThreadEl(node) {
  return node.nodeType === Node.ELEMENT_NODE &&
      node.classList.contains('comment-thread');
}

const COMMIT_MSG_PATH = '/COMMIT_MSG';
/**
 * 72 is the inofficial length standard for git commit messages.
 * Derived from the fact that git log/show appends 4 ws in the beginning of
 * each line when displaying commit messages. To center the commit message
 * in an 80 char terminal a 4 ws border is added to the rightmost side:
 * 4 + 72 + 4
 */
const COMMIT_MSG_LINE_LENGTH = 72;

const RENDER_DIFF_TABLE_DEBOUNCE_NAME = 'renderDiffTable';

/**
 * @extends Polymer.Element
 */
class GrDiff extends mixinBehaviors( [
  PatchSetBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-diff'; }
  /**
   * 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 created
   *
   * @event create-comment
   */

  /**
   * Fired when rendering, including syntax highlighting, is done. Also fired
   * when no rendering can be done because required preferences are not set.
   *
   * @event render
   */

  /**
   * Fired for interaction reporting when a diff context is expanded.
   * Contains an event.detail with numLines about the number of lines that
   * were expanded.
   *
   * @event diff-context-expanded
   */

  static get properties() {
    return {
      changeNum: String,
      noAutoRender: {
        type: Boolean,
        value: false,
      },
      /** @type {?} */
      patchRange: Object,
      path: {
        type: String,
        observer: '_pathObserver',
      },
      prefs: {
        type: Object,
        observer: '_prefsObserver',
      },
      projectName: String,
      displayLine: {
        type: Boolean,
        value: false,
      },
      isImageDiff: {
        type: Boolean,
      },
      commitRange: Object,
      hidden: {
        type: Boolean,
        reflectToAttribute: true,
      },
      noRenderOnPrefsChange: Boolean,
      /** @type {!Array<!Gerrit.HoveredRange>} */
      _commentRanges: {
        type: Array,
        value: () => [],
      },
      /** @type {!Array<!Gerrit.CoverageRange>} */
      coverageRanges: {
        type: Array,
        value: () => [],
      },
      lineWrapping: {
        type: Boolean,
        value: false,
        observer: '_lineWrappingObserver',
      },
      viewMode: {
        type: String,
        value: DiffViewMode.SIDE_BY_SIDE,
        observer: '_viewModeObserver',
      },

      /** @type {?Gerrit.LineOfInterest} */
      lineOfInterest: Object,

      loading: {
        type: Boolean,
        value: false,
        observer: '_loadingChanged',
      },

      loggedIn: {
        type: Boolean,
        value: false,
      },
      diff: {
        type: Object,
        observer: '_diffChanged',
      },
      _diffHeaderItems: {
        type: Array,
        value: [],
        computed: '_computeDiffHeaderItems(diff.*)',
      },
      _diffTableClass: {
        type: String,
        value: '',
      },
      /** @type {?Object} */
      baseImage: Object,
      /** @type {?Object} */
      revisionImage: Object,

      /**
       * Whether the safety check for large diffs when whole-file is set has
       * been bypassed. If the value is null, then the safety has not been
       * bypassed. If the value is a number, then that number represents the
       * context preference to use when rendering the bypassed diff.
       *
       * @type {number|null}
       */
      _safetyBypass: {
        type: Number,
        value: null,
      },

      _showWarning: Boolean,

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

      /** @type {?Object} */
      blame: {
        type: Object,
        value: null,
        observer: '_blameChanged',
      },

      parentIndex: Number,

      showNewlineWarningLeft: {
        type: Boolean,
        value: false,
      },
      showNewlineWarningRight: {
        type: Boolean,
        value: false,
      },

      _newlineWarning: {
        type: String,
        computed: '_computeNewlineWarning(' +
            'showNewlineWarningLeft, showNewlineWarningRight)',
      },

      _diffLength: Number,

      /**
       * Observes comment nodes added or removed after the initial render.
       * Can be used to unregister when the entire diff is (re-)rendered or upon
       * detachment.
       *
       * @type {?PolymerDomApi.ObserveHandle}
       */
      _incrementalNodeObserver: Object,

      /**
       * Observes comment nodes added or removed at any point.
       * Can be used to unregister upon detachment.
       *
       * @type {?PolymerDomApi.ObserveHandle}
       */
      _nodeObserver: Object,

      /** Set by Polymer. */
      isAttached: Boolean,
      layers: Array,
    };
  }

  static get observers() {
    return [
      '_enableSelectionObserver(loggedIn, isAttached)',
    ];
  }

  /** @override */
  created() {
    super.created();
    this.addEventListener('create-range-comment',
        e => this._handleCreateRangeComment(e));
    this.addEventListener('render-content',
        () => this._handleRenderContent());
  }

  /** @override */
  attached() {
    super.attached();
    this._observeNodes();
  }

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

  showNoChangeMessage(loading, prefs, diffLength) {
    return !loading &&
      prefs && prefs.ignore_whitespace !== 'IGNORE_NONE' &&
      diffLength === 0;
  }

  _enableSelectionObserver(loggedIn, isAttached) {
    // Polymer 2: check for undefined
    if ([loggedIn, isAttached].some(arg => arg === undefined)) {
      return;
    }

    if (loggedIn && isAttached) {
      this.listen(document, 'selectionchange', '_handleSelectionChange');
      this.listen(document, 'mouseup', '_handleMouseUp');
    } else {
      this.unlisten(document, 'selectionchange', '_handleSelectionChange');
      this.unlisten(document, 'mouseup', '_handleMouseUp');
    }
  }

  _handleSelectionChange() {
    // Because of shadow DOM selections, we handle the selectionchange here,
    // and pass the shadow DOM selection into gr-diff-highlight, where the
    // corresponding range is determined and normalized.
    const selection = this._getShadowOrDocumentSelection();
    this.$.highlights.handleSelectionChange(selection, false);
  }

  _handleMouseUp(e) {
    // To handle double-click outside of text creating comments, we check on
    // mouse-up if there's a selection that just covers a line change. We
    // can't do that on selection change since the user may still be dragging.
    const selection = this._getShadowOrDocumentSelection();
    this.$.highlights.handleSelectionChange(selection, true);
  }

  /** Gets the current selection, preferring the shadow DOM selection. */
  _getShadowOrDocumentSelection() {
    // When using native shadow DOM, the selection returned by
    // document.getSelection() cannot reference the actual DOM elements making
    // up the diff, because they are in the shadow DOM of the gr-diff element.
    // This takes the shadow DOM selection if one exists.
    return this.root.getSelection ?
      this.root.getSelection() :
      document.getSelection();
  }

  _observeNodes() {
    this._nodeObserver = dom(this).observeNodes(info => {
      const addedThreadEls = info.addedNodes.filter(isThreadEl);
      const removedThreadEls = info.removedNodes.filter(isThreadEl);
      this._updateRanges(addedThreadEls, removedThreadEls);
      this._redispatchHoverEvents(addedThreadEls);
    });
  }

  _updateRanges(addedThreadEls, removedThreadEls) {
    function commentRangeFromThreadEl(threadEl) {
      const side = threadEl.getAttribute('comment-side');
      const range = JSON.parse(threadEl.getAttribute('range'));
      return {side, range, hovering: false};
    }

    const addedCommentRanges = addedThreadEls
        .map(commentRangeFromThreadEl)
        .filter(({range}) => range);
    const removedCommentRanges = removedThreadEls
        .map(commentRangeFromThreadEl)
        .filter(({range}) => range);
    for (const removedCommentRange of removedCommentRanges) {
      const i = this._commentRanges
          .findIndex(
              cr => cr.side === removedCommentRange.side &&
            rangesEqual(cr.range, removedCommentRange.range)
          );
      this.splice('_commentRanges', i, 1);
    }

    if (addedCommentRanges && addedCommentRanges.length) {
      this.push('_commentRanges', ...addedCommentRanges);
    }
  }

  /**
   * The key locations based on the comments and line of interests,
   * where lines should not be collapsed.
   *
   * @return {{left: Object<(string|number), boolean>,
   *     right: Object<(string|number), boolean>}}
   */
  _computeKeyLocations() {
    const keyLocations = {left: {}, right: {}};
    if (this.lineOfInterest) {
      const side = this.lineOfInterest.leftSide ? 'left' : 'right';
      keyLocations[side][this.lineOfInterest.number] = true;
    }
    const threadEls = dom(this).getEffectiveChildNodes()
        .filter(isThreadEl);

    for (const threadEl of threadEls) {
      const commentSide = threadEl.getAttribute('comment-side');
      const lineNum = Number(threadEl.getAttribute('line-num')) ||
          GrDiffLine.FILE;
      const commentRange = threadEl.range || {};
      keyLocations[commentSide][lineNum] = true;
      // Add start_line as well if exists,
      // the being and end of the range should not be collapsed.
      if (commentRange.start_line) {
        keyLocations[commentSide][commentRange.start_line] = true;
      }
    }
    return keyLocations;
  }

  // Dispatch events that are handled by the gr-diff-highlight.
  _redispatchHoverEvents(addedThreadEls) {
    for (const threadEl of addedThreadEls) {
      threadEl.addEventListener('mouseenter', () => {
        threadEl.dispatchEvent(new CustomEvent(
            'comment-thread-mouseenter', {bubbles: true, composed: true}));
      });
      threadEl.addEventListener('mouseleave', () => {
        threadEl.dispatchEvent(new CustomEvent(
            'comment-thread-mouseleave', {bubbles: true, composed: true}));
      });
    }
  }

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

  /** @return {!Array<!HTMLElement>} */
  getCursorStops() {
    if (this.hidden && this.noAutoRender) {
      return [];
    }

    return Array.from(
        dom(this.root).querySelectorAll(':not(.contextControl) > .diff-row'));
  }

  /** @return {boolean} */
  isRangeSelected() {
    return !!this.$.highlights.selectedRange;
  }

  toggleLeftDiff() {
    this.toggleClass('no-left');
  }

  _blameChanged(newValue) {
    this.$.diffBuilder.setBlame(newValue);
    if (newValue) {
      this.classList.add('showBlame');
    } else {
      this.classList.remove('showBlame');
    }
  }

  /** @return {string} */
  _computeContainerClass(loggedIn, viewMode, displayLine) {
    const classes = ['diffContainer'];
    switch (viewMode) {
      case DiffViewMode.UNIFIED:
        classes.push('unified');
        break;
      case DiffViewMode.SIDE_BY_SIDE:
        classes.push('sideBySide');
        break;
      default:
        throw Error('Invalid view mode: ', viewMode);
    }
    if (getHiddenScroll()) {
      classes.push('hiddenscroll');
    }
    if (loggedIn) {
      classes.push('canComment');
    }
    if (displayLine) {
      classes.push('displayLine');
    }
    return classes.join(' ');
  }

  _handleTap(e) {
    const el = dom(e).localTarget;

    if (el.classList.contains('showContext')) {
      this.dispatchEvent(new CustomEvent('diff-context-expanded', {
        detail: {
          numLines: e.detail.numLines,
        },
        composed: true, bubbles: true,
      }));
      this.$.diffBuilder.showContext(e.detail.groups, e.detail.section);
    } else if (el.classList.contains('lineNum') ||
               el.classList.contains('lineNumButton')) {
      this.addDraftAtLine(el);
    } else if (el.tagName === 'HL' ||
        el.classList.contains('content') ||
        el.classList.contains('contentText')) {
      const target = this.$.diffBuilder.getLineElByChild(el);
      if (target) { this._selectLine(target); }
    }
  }

  _selectLine(el) {
    this.dispatchEvent(new CustomEvent('line-selected', {
      detail: {
        side: el.classList.contains('left') ? DiffSide.LEFT : DiffSide.RIGHT,
        number: el.getAttribute('data-value'),
        path: this.path,
      },
      composed: true, bubbles: true,
    }));
  }

  addDraftAtLine(el) {
    this._selectLine(el);
    if (!this._isValidElForComment(el)) { return; }

    const value = el.getAttribute('data-value');
    let lineNum;
    if (value !== GrDiffLine.FILE) {
      lineNum = parseInt(value, 10);
      if (isNaN(lineNum)) {
        this.dispatchEvent(new CustomEvent('show-alert', {
          detail: {message: ERR_INVALID_LINE + value},
          composed: true, bubbles: true,
        }));
        return;
      }
    }
    this._createComment(el, lineNum);
  }

  createRangeComment() {
    if (!this.isRangeSelected()) {
      throw Error('Selection is needed for new range comment');
    }
    const {side, range} = this.$.highlights.selectedRange;
    this._createCommentForSelection(side, range);
  }

  _createCommentForSelection(side, range) {
    const lineNum = range.end_line;
    const lineEl = this.$.diffBuilder.getLineElByNumber(lineNum, side);
    if (this._isValidElForComment(lineEl)) {
      this._createComment(lineEl, lineNum, side, range);
    }
  }

  _handleCreateRangeComment(e) {
    const range = e.detail.range;
    const side = e.detail.side;
    this._createCommentForSelection(side, range);
  }

  /** @return {boolean} */
  _isValidElForComment(el) {
    if (!this.loggedIn) {
      this.dispatchEvent(new CustomEvent('show-auth-required', {
        composed: true, bubbles: true,
      }));
      return false;
    }
    const patchNum = el.classList.contains(DiffSide.LEFT) ?
      this.patchRange.basePatchNum :
      this.patchRange.patchNum;

    const isEdit = this.patchNumEquals(patchNum, this.EDIT_NAME);
    const isEditBase = this.patchNumEquals(patchNum, this.PARENT_NAME) &&
        this.patchNumEquals(this.patchRange.patchNum, this.EDIT_NAME);

    if (isEdit) {
      this.dispatchEvent(new CustomEvent('show-alert', {
        detail: {message: ERR_COMMENT_ON_EDIT},
        composed: true, bubbles: true,
      }));
      return false;
    } else if (isEditBase) {
      this.dispatchEvent(new CustomEvent('show-alert', {
        detail: {message: ERR_COMMENT_ON_EDIT_BASE},
        composed: true, bubbles: true,
      }));
      return false;
    }
    return true;
  }

  /**
   * @param {!Object} lineEl
   * @param {number=} lineNum
   * @param {string=} side
   * @param {!Object=} range
   */
  _createComment(lineEl, lineNum, side, range) {
    const contentText = this.$.diffBuilder.getContentByLineEl(lineEl);
    if (!contentText) {
      return;
    }
    const contentEl = contentText.parentElement;
    side = side ||
        this._getCommentSideByLineAndContent(lineEl, contentEl);
    const patchForNewThreads = this._getPatchNumByLineAndContent(
        lineEl, contentEl);
    const isOnParent =
        this._getIsParentCommentByLineAndContent(lineEl, contentEl);
    this.dispatchEvent(new CustomEvent('create-comment', {
      bubbles: true,
      composed: true,
      detail: {
        lineNum,
        side,
        patchNum: patchForNewThreads,
        isOnParent,
        range,
      },
    }));
  }

  _getThreadGroupForLine(contentEl) {
    return contentEl.querySelector('.thread-group');
  }

  /**
   * Gets or creates a comment thread group for a specific line and side on a
   * diff.
   *
   * @param {!Object} contentEl
   * @param {!DiffSide} commentSide
   * @return {!Node}
   */
  _getOrCreateThreadGroup(contentEl, commentSide) {
    // Check if thread group exists.
    let threadGroupEl = this._getThreadGroupForLine(contentEl);
    if (!threadGroupEl) {
      threadGroupEl = document.createElement('div');
      threadGroupEl.className = 'thread-group';
      threadGroupEl.setAttribute('data-side', commentSide);
      contentEl.appendChild(threadGroupEl);
    }
    return threadGroupEl;
  }

  /**
   * The value to be used for the patch number of new comments created at the
   * given line and content elements.
   *
   * In two cases of creating a comment on the left side, the patch number to
   * be used should actually be right side of the patch range:
   * - When the patch range is against the parent comment of a normal change.
   *   Such comments declare themmselves to be on the left using side=PARENT.
   * - If the patch range is against the indexed parent of a merge change.
   *   Such comments declare themselves to be on the given parent by
   *   specifying the parent index via parent=i.
   *
   * @return {number}
   */
  _getPatchNumByLineAndContent(lineEl, contentEl) {
    let patchNum = this.patchRange.patchNum;

    if ((lineEl.classList.contains(DiffSide.LEFT) ||
        contentEl.classList.contains('remove')) &&
        this.patchRange.basePatchNum !== 'PARENT' &&
        !this.isMergeParent(this.patchRange.basePatchNum)) {
      patchNum = this.patchRange.basePatchNum;
    }
    return patchNum;
  }

  /** @return {boolean} */
  _getIsParentCommentByLineAndContent(lineEl, contentEl) {
    if ((lineEl.classList.contains(DiffSide.LEFT) ||
        contentEl.classList.contains('remove')) &&
        (this.patchRange.basePatchNum === 'PARENT' ||
        this.isMergeParent(this.patchRange.basePatchNum))) {
      return true;
    }
    return false;
  }

  /** @return {string} */
  _getCommentSideByLineAndContent(lineEl, contentEl) {
    let side = 'right';
    if (lineEl.classList.contains(DiffSide.LEFT) ||
        contentEl.classList.contains('remove')) {
      side = 'left';
    }
    return side;
  }

  _prefsObserver(newPrefs, oldPrefs) {
    // Scan the preference objects one level deep to see if they differ.
    let differ = !oldPrefs;
    if (newPrefs && oldPrefs) {
      for (const key in newPrefs) {
        if (newPrefs[key] !== oldPrefs[key]) {
          differ = true;
        }
      }
    }

    if (differ) {
      this._prefsChanged(newPrefs);
    }
  }

  _pathObserver() {
    // Call _prefsChanged(), because line-limit style value depends on path.
    this._prefsChanged(this.prefs);
  }

  _viewModeObserver() {
    this._prefsChanged(this.prefs);
  }

  _cleanup() {
    this.cancel();
    this._blame = null;
    this._safetyBypass = null;
    this._showWarning = false;
    this.clearDiffContent();
  }

  /** @param {boolean} newValue */
  _loadingChanged(newValue) {
    if (newValue) {
      this._cleanup();
    }
  }

  _lineWrappingObserver() {
    this._prefsChanged(this.prefs);
  }

  _prefsChanged(prefs) {
    if (!prefs) { return; }

    this._blame = null;

    const lineLength = this.path === COMMIT_MSG_PATH ?
      COMMIT_MSG_LINE_LENGTH : prefs.line_length;
    const stylesToUpdate = {};

    if (prefs.line_wrapping) {
      this._diffTableClass = 'full-width';
      if (this.viewMode === 'SIDE_BY_SIDE') {
        stylesToUpdate['--content-width'] = 'none';
        stylesToUpdate['--line-limit'] = lineLength + 'ch';
      }
    } else {
      this._diffTableClass = '';
      stylesToUpdate['--content-width'] = lineLength + 'ch';
    }

    if (prefs.font_size) {
      stylesToUpdate['--font-size'] = prefs.font_size + 'px';
    }

    this.updateStyles(stylesToUpdate);

    if (this.diff && !this.noRenderOnPrefsChange) {
      this._debounceRenderDiffTable();
    }
  }

  _diffChanged(newValue) {
    if (newValue) {
      this._cleanup();
      this._diffLength = this.getDiffLength(newValue);
      this._debounceRenderDiffTable();
    }
  }

  /**
   * When called multiple times from the same microtask, will call
   * _renderDiffTable only once, in the next microtask, unless it is cancelled
   * before that microtask runs.
   *
   * This should be used instead of calling _renderDiffTable directly to
   * render the diff in response to an input change, because there may be
   * multiple inputs changing in the same microtask, but we only want to
   * render once.
   */
  _debounceRenderDiffTable() {
    this.debounce(
        RENDER_DIFF_TABLE_DEBOUNCE_NAME, () => this._renderDiffTable());
  }

  _renderDiffTable() {
    if (!this.prefs) {
      this.dispatchEvent(
          new CustomEvent('render', {bubbles: true, composed: true}));
      return;
    }
    if (this.prefs.context === -1 &&
        this._diffLength >= LARGE_DIFF_THRESHOLD_LINES &&
        this._safetyBypass === null) {
      this._showWarning = true;
      this.dispatchEvent(
          new CustomEvent('render', {bubbles: true, composed: true}));
      return;
    }

    this._showWarning = false;

    const keyLocations = this._computeKeyLocations();
    this.$.diffBuilder.render(keyLocations, this._getBypassPrefs())
        .then(() => {
          this.dispatchEvent(
              new CustomEvent('render', {
                bubbles: true,
                composed: true,
                detail: {contentRendered: true},
              }));
        });
  }

  _handleRenderContent() {
    this._unobserveIncrementalNodes();
    this._incrementalNodeObserver = dom(this).observeNodes(info => {
      const addedThreadEls = info.addedNodes.filter(isThreadEl);
      // Removed nodes do not need to be handled because all this code does is
      // adding a slot for the added thread elements, and the extra slots do
      // not hurt. It's probably a bigger performance cost to remove them than
      // to keep them around. Medium term we can even consider to add one slot
      // for each line from the start.
      let lastEl;
      for (const threadEl of addedThreadEls) {
        const lineNumString = threadEl.getAttribute('line-num') || 'FILE';
        const commentSide = threadEl.getAttribute('comment-side');
        const lineEl = this.$.diffBuilder.getLineElByNumber(
            lineNumString, commentSide);
        const contentText = this.$.diffBuilder.getContentByLineEl(lineEl);
        if (!contentText) {
          continue;
        }
        const contentEl = contentText.parentElement;
        const threadGroupEl = this._getOrCreateThreadGroup(
            contentEl, commentSide);
        // Create a slot for the thread and attach it to the thread group.
        // The Polyfill has some bugs and this only works if the slot is
        // attached to the group after the group is attached to the DOM.
        // The thread group may already have a slot with the right name, but
        // that is okay because the first matching slot is used and the rest
        // are ignored.
        const slot = document.createElement('slot');
        slot.name = threadEl.getAttribute('slot');
        dom(threadGroupEl).appendChild(slot);
        lastEl = threadEl;
      }

      // Safari is not binding newly created comment-thread
      // with the slot somehow, replace itself will rebind it
      // @see Issue 11182
      if (lastEl && lastEl.replaceWith) {
        lastEl.replaceWith(lastEl);
      }
    });
  }

  _unobserveIncrementalNodes() {
    if (this._incrementalNodeObserver) {
      dom(this).unobserveNodes(this._incrementalNodeObserver);
    }
  }

  _unobserveNodes() {
    if (this._nodeObserver) {
      dom(this).unobserveNodes(this._nodeObserver);
    }
  }

  /**
   * Get the preferences object including the safety bypass context (if any).
   */
  _getBypassPrefs() {
    if (this._safetyBypass !== null) {
      return Object.assign({}, this.prefs, {context: this._safetyBypass});
    }
    return this.prefs;
  }

  clearDiffContent() {
    this._unobserveIncrementalNodes();
    this.$.diffTable.innerHTML = null;
  }

  /** @return {!Array} */
  _computeDiffHeaderItems(diffInfoRecord) {
    const diffInfo = diffInfoRecord.base;
    if (!diffInfo || !diffInfo.diff_header) { return []; }
    return diffInfo.diff_header
        .filter(item => !(item.startsWith('diff --git ') ||
          item.startsWith('index ') ||
          item.startsWith('+++ ') ||
          item.startsWith('--- ') ||
          item === 'Binary files differ'));
  }

  /** @return {boolean} */
  _computeDiffHeaderHidden(items) {
    return items.length === 0;
  }

  _handleFullBypass() {
    this._safetyBypass = FULL_CONTEXT;
    this._debounceRenderDiffTable();
  }

  _handleLimitedBypass() {
    this._safetyBypass = LIMITED_CONTEXT;
    this._debounceRenderDiffTable();
  }

  /** @return {string} */
  _computeWarningClass(showWarning) {
    return showWarning ? 'warn' : '';
  }

  /**
   * @param {string} errorMessage
   * @return {string}
   */
  _computeErrorClass(errorMessage) {
    return errorMessage ? 'showError' : '';
  }

  expandAllContext() {
    this._handleFullBypass();
  }

  /**
   * @param {!boolean} warnLeft
   * @param {!boolean} warnRight
   * @return {string|null}
   */
  _computeNewlineWarning(warnLeft, warnRight) {
    const messages = [];
    if (warnLeft) {
      messages.push(NO_NEWLINE_BASE);
    }
    if (warnRight) {
      messages.push(NO_NEWLINE_REVISION);
    }
    if (!messages.length) { return null; }
    return messages.join(' — ');
  }

  /**
   * @param {string} warning
   * @param {boolean} loading
   * @return {string}
   */
  _computeNewlineWarningClass(warning, loading) {
    if (loading || !warning) { return 'newlineWarning hidden'; }
    return 'newlineWarning';
  }

  /**
   * Get the approximate length of the diff as the sum of the maximum
   * length of the chunks.
   *
   * @param {Object} diff object
   * @return {number}
   */
  getDiffLength(diff) {
    if (!diff) return 0;
    return diff.content.reduce((sum, sec) => {
      if (sec.hasOwnProperty('ab')) {
        return sum + sec.ab.length;
      } else {
        return sum + Math.max(
            sec.hasOwnProperty('a') ? sec.a.length : 0,
            sec.hasOwnProperty('b') ? sec.b.length : 0);
      }
    }, 0);
  }
}

customElements.define(GrDiff.is, GrDiff);
