/**
 * @license
 * Copyright (C) 2016 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.
 */
(function() {
  'use strict';

  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 DiffSide = {
    LEFT: 'left',
    RIGHT: 'right',
  };

  const Defs = {};

  /**
   * Special line number which should not be collapsed into a shared region.
   *
   * @typedef {{
   *  number: number,
   *  leftSide: boolean
   * }}
   */
  Defs.LineOfInterest;

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

  /** @typedef {{start_line: number, start_character: number,
   *             end_line: number, end_character: number}} */
  Gerrit.Range;

  /**
   * Compare two ranges. Either argument may be falsy, but will only return
   * true if both are falsy or if neither are falsy and have the same position
   * values.
   *
   * @param {Gerrit.Range=} a range 1
   * @param {Gerrit.Range=} b range 2
   * @return {boolean}
   */
  Gerrit.rangesEqual = function(a, b) {
    if (!a && !b) { return true; }
    if (!a || !b) { return false; }
    return a.start_line === b.start_line &&
        a.start_character === b.start_character &&
        a.end_line === b.end_line &&
        a.end_character === b.end_character;
  };

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

  /**
   * Turn a slot element into the corresponding content element.
   * Slots are only fully supported in Polymer 2 - in Polymer 1, they are
   * replaced with content elements during template parsing. This conversion is
   * not applied for imperatively created slot elements, so this method
   * implements the same behavior as the template parsing for imperative slots.
   */
  Gerrit.slotToContent = function(slot) {
    const content = document.createElement('content');
    content.name = slot.name;
    content.setAttribute('select', `[slot='${slot.name}']`);
    return content;
  };

  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';

  Polymer({
    is: 'gr-diff',
    _legacyUndefinedCheck: true,

    /**
     * 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
     */

    properties: {
      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: () => [],
      },
      lineWrapping: {
        type: Boolean,
        value: false,
        observer: '_lineWrappingObserver',
      },
      viewMode: {
        type: String,
        value: DiffViewMode.SIDE_BY_SIDE,
        observer: '_viewModeObserver',
      },

      /** @type {?Defs.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,

      _newlineWarning: {
        type: String,
        computed: '_computeNewlineWarning(diff)',
      },

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

    behaviors: [
      Gerrit.PatchSetBehavior,
    ],

    listeners: {
      'create-range-comment': '_handleCreateRangeComment',
      'render-content': '_handleRenderContent',
    },

    observers: [
      '_enableSelectionObserver(loggedIn, isAttached)',
    ],

    attached() {
      this._observeNodes();
    },

    detached() {
      this._unobserveIncrementalNodes();
      this._unobserveNodes();
    },

    _enableSelectionObserver(loggedIn, isAttached) {
      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 = Polymer.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(commentRange => {
          return commentRange.side === removedCommentRange.side &&
              Gerrit.rangesEqual(commentRange.range, removedCommentRange.range);
        });
        this.splice('_commentRanges', i, 1);
      }
      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 = Polymer.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;
        keyLocations[commentSide][lineNum] = 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}));
        });
        threadEl.addEventListener('mouseleave', () => {
          threadEl.dispatchEvent(
              new CustomEvent('comment-thread-mouseleave', {bubbles: 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 [];
      }

      // Polymer2: querySelectorAll returns NodeList instead of Array.
      return Array.from(
          Polymer.dom(this.root).querySelectorAll('.diff-row'));
    },

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

    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 (Gerrit.hiddenscroll) {
        classes.push('hiddenscroll');
      }
      if (loggedIn) {
        classes.push('canComment');
      }
      if (displayLine) {
        classes.push('displayLine');
      }
      return classes.join(' ');
    },

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

      if (el.classList.contains('showContext')) {
        this.$.diffBuilder.showContext(e.detail.groups, e.detail.section);
      } else if (el.classList.contains('lineNum')) {
        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.fire('line-selected', {
        side: el.classList.contains('left') ? DiffSide.LEFT : DiffSide.RIGHT,
        number: el.getAttribute('data-value'),
        path: this.path,
      });
    },

    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.fire('show-alert', {message: ERR_INVALID_LINE + value});
          return;
        }
      }
      this._createComment(el, lineNum);
    },

    _handleCreateRangeComment(e) {
      const range = e.detail.range;
      const side = e.detail.side;
      const lineNum = range.end_line;
      const lineEl = this.$.diffBuilder.getLineElByNumber(lineNum, side);

      if (this._isValidElForComment(lineEl)) {
        this._createComment(lineEl, lineNum, side, range);
      }
    },

    /** @return {boolean} */
    _isValidElForComment(el) {
      if (!this.loggedIn) {
        this.fire('show-auth-required');
        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.fire('show-alert', {message: ERR_COMMENT_ON_EDIT});
        return false;
      } else if (isEditBase) {
        this.fire('show-alert', {message: ERR_COMMENT_ON_EDIT_BASE});
        return false;
      }
      return true;
    },

    /**
     * @param {!Object} lineEl
     * @param {number=} lineNum
     * @param {string=} side
     * @param {!Object=} range
     */
    _createComment(lineEl, lineNum=undefined, side=undefined, range=undefined) {
      const contentText = this.$.diffBuilder.getContentByLineEl(lineEl);
      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,
        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 {!Gerrit.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);
    },

    /** @param {boolean} newValue */
    _loadingChanged(newValue) {
      if (newValue) {
        this.cancel();
        this._blame = null;
        this._safetyBypass = null;
        this._showWarning = false;
        this.clearDiffContent();
      }
    },

    _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._diffLength = this.$.diffBuilder.getDiffLength();
        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() {
      this._unobserveIncrementalNodes();
      if (!this.prefs) {
        this.dispatchEvent(new CustomEvent('render', {bubbles: 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}));
        return;
      }

      this._showWarning = false;

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

    _handleRenderContent() {
      this._incrementalNodeObserver = Polymer.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.
        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);
          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');
          Polymer.dom(threadGroupEl).appendChild(Gerrit.slotToContent(slot));
        }
      });
    },

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

    _unobserveNodes() {
      if (this._nodeObserver) {
        Polymer.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 => {
        return !(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();
    },

    /**
     * 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) || (!leftSide && !chunk.b)));

      // 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] === '';
    },

    /**
     * @param {!Object} diff
     * @return {string|null}
     */
    _computeNewlineWarning(diff) {
      const hasLeft = this._hasTrailingNewlines(diff, true);
      const hasRight = this._hasTrailingNewlines(diff, false);
      const messages = [];
      if (hasLeft === false) {
        messages.push(NO_NEWLINE_BASE);
      }
      if (hasRight === false) {
        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';
    },
  });
})();
