/**
 * @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 WHOLE_FILE = -1;

  const DiffSide = {
    LEFT: 'left',
    RIGHT: 'right',
  };

  const DiffHighlights = {
    ADDED: 'edit_b',
    REMOVED: 'edit_a',
  };

  /**
   * The maximum size for an addition or removal chunk before it is broken down
   * into a series of chunks that are this size at most.
   *
   * Note: The value of 120 is chosen so that it is larger than the default
   * _asyncThreshold of 64, but feel free to tune this constant to your
   * performance needs.
   */
  const MAX_GROUP_SIZE = 120;

  /**
   * Converts the API's `DiffContent`s  to `GrDiffGroup`s for rendering.
   *
   * This includes a number of tasks:
   *  - adding a group for the "File" pseudo line that file-level comments can
   *    be attached to
   *  - replacing unchanged parts of the diff that are outside the user's
   *    context setting and do not have comments with a group representing the
   *    "expand context" widget. This may require splitting a `DiffContent` so
   *    that the part that is within the context or has comments is shown, while
   *    the rest is not.
   *  - splitting large `DiffContent`s to allow more granular async rendering
   */
  Polymer({
    is: 'gr-diff-processor',
    _legacyUndefinedCheck: true,

    properties: {

      /**
       * The amount of context around collapsed groups.
       */
      context: Number,

      /**
       * The array of groups output by the processor.
       */
      groups: {
        type: Array,
        notify: true,
      },

      /**
       * Locations that should not be collapsed, including the locations of
       * comments.
       */
      keyLocations: {
        type: Object,
        value() { return {left: {}, right: {}}; },
      },

      /**
       * The maximum number of lines to process synchronously.
       */
      _asyncThreshold: {
        type: Number,
        value: 64,
      },

      /** @type {?number} */
      _nextStepHandle: Number,
      /**
       * The promise last returned from `process()` while the asynchronous
       * processing is running - `null` otherwise. Provides a `cancel()`
       * method that rejects it with `{isCancelled: true}`.
       * @type {?Object}
       */
      _processPromise: {
        type: Object,
        value: null,
      },
      _isScrolling: Boolean,
    },

    attached() {
      this.listen(window, 'scroll', '_handleWindowScroll');
    },

    detached() {
      this.cancel();
      this.unlisten(window, 'scroll', '_handleWindowScroll');
    },

    _handleWindowScroll() {
      this._isScrolling = true;
      this.debounce('resetIsScrolling', () => {
        this._isScrolling = false;
      }, 50);
    },

    /**
     * Asynchronously process the diff object into groups. As it processes, it
     * will splice groups into the `groups` property of the component.
     * @return {Promise} A promise that resolves when the diff is completely
     *     processed.
     */
    process(content, isBinary) {
      // Cancel any still running process() calls, because they append to the
      // same groups field.
      this.cancel();

      this.groups = [];
      this.push('groups', this._makeFileComments());

      // If it's a binary diff, we won't be rendering hunks of text differences
      // so finish processing.
      if (isBinary) { return Promise.resolve(); }


      this._processPromise = util.makeCancelable(
          new Promise(resolve => {
            const state = {
              lineNums: {left: 0, right: 0},
              sectionIndex: 0,
            };

            content = this._splitLargeChunks(content);
            content = this._splitUnchangedChunksWithComments(content);

            let currentBatch = 0;
            const nextStep = () => {
              if (this._isScrolling) {
                this.async(nextStep, 100);
                return;
              }
              // If we are done, resolve the promise.
              if (state.sectionIndex >= content.length) {
                resolve(this.groups);
                this._nextStepHandle = null;
                return;
              }

              // Process the next section and incorporate the result.
              const result = this._processNext(
                  state, content[state.sectionIndex], content.length);
              for (const group of result.groups) {
                this.push('groups', group);
                currentBatch += group.lines.length;
              }
              state.lineNums.left += result.lineDelta.left;
              state.lineNums.right += result.lineDelta.right;

              // Increment the index and recurse.
              state.sectionIndex++;
              if (currentBatch >= this._asyncThreshold) {
                currentBatch = 0;
                this._nextStepHandle = this.async(nextStep, 1);
              } else {
                nextStep.call(this);
              }
            };

            nextStep.call(this);
          }));
      return this._processPromise
          .finally(() => { this._processPromise = null; });
    },

    /**
     * Cancel any jobs that are running.
     */
    cancel() {
      if (this._nextStepHandle != null) {
        this.cancelAsync(this._nextStepHandle);
        this._nextStepHandle = null;
      }
      if (this._processPromise) {
        this._processPromise.cancel();
      }
    },

    /**
     * Process the next section of the diff.
     *
     * @param {!Object} state
     * @param {!Object} section
     * @param {number} numSections
     */
    _processNext(state, section, numSections) {
      const lines = this._linesFromSection(
          section, state.lineNums.left + 1, state.lineNums.right + 1);
      const lineDelta = {
        left: section.ab ? section.ab.length : section.a ? section.a.length : 0,
        right: section.ab ? section.ab.length :
            section.b ? section.b.length : 0,
      };
      let groups;
      if (section.ab) { // If it's a shared section.
        let sectionEnd = null;
        if (state.sectionIndex === 0) {
          sectionEnd = 'first';
        } else if (state.sectionIndex === numSections - 1) {
          sectionEnd = 'last';
        }
        groups = this._sharedGroupsFromLines(
            lines,
            lineDelta.left,
            numSections > 1 ? this.context : WHOLE_FILE,
            state.lineNums.left,
            state.lineNums.right,
            sectionEnd);
      } else { // Otherwise it's a delta section.
        const deltaGroup = new GrDiffGroup(GrDiffGroup.Type.DELTA, lines);
        deltaGroup.dueToRebase = section.due_to_rebase;
        groups = [deltaGroup];
      }
      return {lineDelta, groups};
    },

    _linesFromSection(section, offsetLeft, offsetRight) {
      const lines = [];
      if (section.ab) {
        lines.push(...section.ab.map((row, i) =>
          this._lineFromRow(
              GrDiffLine.Type.BOTH, offsetLeft, offsetRight, row, i)));
      }
      if (section.a) {
        lines.push(...this._deltaLinesFromRows(
            GrDiffLine.Type.REMOVE, section.a, offsetLeft,
            section[DiffHighlights.REMOVED]));
      }
      if (section.b) {
        lines.push(...this._deltaLinesFromRows(
            GrDiffLine.Type.ADD, section.b, offsetRight,
            section[DiffHighlights.ADDED]));
      }
      return lines;
    },

    /**
     * @return {!Array<!Object>} Array of GrDiffLines
     */
    _deltaLinesFromRows(lineType, rows, offset, opt_highlights) {
      // Normalize highlights if they have been passed.
      if (opt_highlights) {
        opt_highlights = this._normalizeIntralineHighlights(rows,
            opt_highlights);
      }
      return rows.map((row, i) =>
          this._lineFromRow(lineType, offset, offset, row, i, opt_highlights));
    },

    /**
     * @param {string} type (GrDiffLine.Type)
     * @param {number} offsetLeft
     * @param {number} offsetRight
     * @param {string} row
     * @param {number} i
     * @param {!Array<!Object>=} opt_highlights
     * @return {!Object} (GrDiffLine)
     */
    _lineFromRow(type, offsetLeft, offsetRight, row, i, opt_highlights) {
      const line = new GrDiffLine(type);
      line.text = row;
      if (type !== GrDiffLine.Type.ADD) line.beforeNumber = offsetLeft + i;
      if (type !== GrDiffLine.Type.REMOVE) line.afterNumber = offsetRight + i;
      if (opt_highlights) {
        line.highlights = opt_highlights.filter(hl => hl.contentIndex === i);
      }
      return line;
    },


    /**
     * Take rows of a shared diff section and produce an array of corresponding
     * (potentially collapsed) groups.
     * @param {!Array<string>} lines
     * @param {number} numLines
     * @param {number} context
     * @param {number} startLineNumLeft
     * @param {number} startLineNumRight
     * @param {?string=} opt_sectionEnd String representing whether this is the
     *     first section or the last section or neither. Use the values 'first',
     *     'last' and null respectively.
     * @return {!Array<!Object>} Array of GrDiffGroup
     */
    _sharedGroupsFromLines(lines, numLines, context, startLineNumLeft,
        startLineNumRight, opt_sectionEnd) {
      // Find the hidden range based on the user's context preference. If this
      // is the first or the last section of the diff, make sure the collapsed
      // part of the section extends to the edge of the file.
      const hiddenRangeStart = opt_sectionEnd === 'first' ? 0 : context;
      const hiddenRangeEnd = opt_sectionEnd === 'last' ?
          numLines : numLines - context;

      const result = [];
      // If there is a range to hide.
      if (context !== WHOLE_FILE && hiddenRangeEnd - hiddenRangeStart > 1) {
        const linesBeforeCtx = [];
        const hiddenLines = [];
        const linesAfterCtx = [];
        for (const line of lines) {
          // In the case there are no changes, these are the same.
          // In the case of ignored whitespace changes, either only one is set,
          // or the are the same.
          const lineOffset = line.beforeNumber ?
              line.beforeNumber - startLineNumLeft - 1 :
              line.afterNumber - startLineNumRight - 1;
          if (lineOffset < hiddenRangeStart) linesBeforeCtx.push(line);
          else if (hiddenRangeEnd <= lineOffset) linesAfterCtx.push(line);
          else hiddenLines.push(line);
        }

        if (linesBeforeCtx.length > 0) {
          result.push(new GrDiffGroup(GrDiffGroup.Type.BOTH, linesBeforeCtx));
        }

        const ctxLine = new GrDiffLine(GrDiffLine.Type.CONTEXT_CONTROL);
        ctxLine.contextGroups =
            [new GrDiffGroup(GrDiffGroup.Type.BOTH, hiddenLines)];
        result.push(new GrDiffGroup(GrDiffGroup.Type.CONTEXT_CONTROL,
            [ctxLine]));

        if (linesAfterCtx.length > 0) {
          result.push(new GrDiffGroup(GrDiffGroup.Type.BOTH, linesAfterCtx));
        }
      } else {
        result.push(new GrDiffGroup(GrDiffGroup.Type.BOTH, lines));
      }

      return result;
    },

    _makeFileComments() {
      const line = new GrDiffLine(GrDiffLine.Type.BOTH);
      line.beforeNumber = GrDiffLine.FILE;
      line.afterNumber = GrDiffLine.FILE;
      return new GrDiffGroup(GrDiffGroup.Type.BOTH, [line]);
    },


    /**
     * Split chunks into smaller chunks of the same kind.
     *
     * This is done to prevent doing too much work on the main thread in one
     * uninterrupted rendering step, which would make the browser unresponsive.
     *
     * Note that in the case of unmodified chunks, we only split chunks if the
     * context is set to file (because otherwise they are split up further down
     * the processing into the visible and hidden context), and only split it
     * into 2 chunks, one max sized one and the rest (for reasons that are
     * unclear to me).
     *
     * @param {!Array<!Object>} chunks Chunks as returned from the server
     * @return {!Array<!Object>} Finer grained chunks.
     */
    _splitLargeChunks(chunks) {
      const newChunks = [];

      for (const chunk of chunks) {
        if (!chunk.ab) {
          for (const group of this._breakdownGroup(chunk)) {
            newChunks.push(group);
          }
          continue;
        }

        // If the context is set to "whole file", then break down the shared
        // chunks so they can be rendered incrementally. Note: this is not
        // enabled for any other context preference because manipulating the
        // chunks in this way violates assumptions by the context grouper logic.
        if (this.context === -1 && chunk.ab.length > MAX_GROUP_SIZE * 2) {
          // Split large shared groups in two, where the first is the maximum
          // group size.
          newChunks.push({ab: chunk.ab.slice(0, MAX_GROUP_SIZE)});
          newChunks.push({ab: chunk.ab.slice(MAX_GROUP_SIZE)});
        } else {
          newChunks.push(chunk);
        }
      }
      return newChunks;
    },

    /**
     * In order to show comments out of the bounds of the selected context,
     * treat them as separate chunks within the model so that the content (and
     * context surrounding it) renders correctly.
     * @param {!Array<!Object>} chunks DiffContents as returned from server.
     * @return {!Array<!Object>} Finer grained DiffContents.
     */
    _splitUnchangedChunksWithComments(chunks) {
      const result = [];
      let leftLineNum = 1;
      let rightLineNum = 1;

      for (const chunk of chunks) {
        // If it isn't a common chunk, append it as-is and update line numbers.
        if (!chunk.ab && !chunk.common) {
          if (chunk.a) {
            leftLineNum += chunk.a.length;
          }
          if (chunk.b) {
            rightLineNum += chunk.b.length;
          }
          result.push(chunk);
          continue;
        }

        if (chunk.common && chunk.a.length != chunk.b.length) {
          throw new Error(
            'DiffContent with common=true must always have equal length');
        }
        const numLines = chunk.ab ? chunk.ab.length : chunk.a.length;
        const chunkEnds = this._findChunkEndsAtKeyLocations(
            numLines, leftLineNum, rightLineNum);
        leftLineNum += numLines;
        rightLineNum += numLines;

        if (chunk.ab) {
          result.push(...this._splitAtChunkEnds(chunk.ab, chunkEnds)
              .map(lines => Object.assign({}, chunk, {ab: lines})));
        } else if (chunk.common) {
          const aChunks = this._splitAtChunkEnds(chunk.a, chunkEnds);
          const bChunks = this._splitAtChunkEnds(chunk.b, chunkEnds);
          result.push(...aChunks.map((lines, i) =>
              Object.assign({}, chunk, {a: lines, b: bChunks[i]})));
        }
      }

      return result;
    },

    _findChunkEndsAtKeyLocations(numLines, leftOffset, rightOffset) {
      const result = [];
      let lastChunkEnd = 0;
      for (let i=0; i<numLines; i++) {
        // If this line should not be collapsed.
        if (this.keyLocations[DiffSide.LEFT][leftOffset + i] ||
            this.keyLocations[DiffSide.RIGHT][rightOffset + i]) {
          // If any lines have been accumulated into the chunk leading up to
          // this non-collapse line, then add them as a chunk and start a new
          // one.
          if (i > lastChunkEnd) {
            result.push(i);
            lastChunkEnd = i;
          }

          // Add the non-collapse line as its own chunk.
          result.push(i + 1);
        }
      }

      if (numLines > lastChunkEnd) {
        result.push(numLines);
      }

      return result;
    },

    _splitAtChunkEnds(lines, chunkEnds) {
      const result = [];
      let lastChunkEnd = 0;
      for (const chunkEnd of chunkEnds) {
        result.push(lines.slice(lastChunkEnd, chunkEnd));
        lastChunkEnd = chunkEnd;
      }
      return result;
    },

    /**
     * The `highlights` array consists of a list of <skip length, mark length>
     * pairs, where the skip length is the number of characters between the
     * end of the previous edit and the start of this edit, and the mark
     * length is the number of edited characters following the skip. The start
     * of the edits is from the beginning of the related diff content lines.
     *
     * Note that the implied newline character at the end of each line is
     * included in the length calculation, and thus it is possible for the
     * edits to span newlines.
     *
     * A line highlight object consists of three fields:
     * - contentIndex: The index of the diffChunk `content` field (the line
     *   being referred to).
     * - startIndex: Where the highlight should begin.
     * - endIndex: (optional) Where the highlight should end. If omitted, the
     *   highlight is meant to be a continuation onto the next line.
     */
    _normalizeIntralineHighlights(content, highlights) {
      let contentIndex = 0;
      let idx = 0;
      const normalized = [];
      for (const hl of highlights) {
        let line = content[contentIndex] + '\n';
        let j = 0;
        while (j < hl[0]) {
          if (idx === line.length) {
            idx = 0;
            line = content[++contentIndex] + '\n';
            continue;
          }
          idx++;
          j++;
        }
        let lineHighlight = {
          contentIndex,
          startIndex: idx,
        };

        j = 0;
        while (line && j < hl[1]) {
          if (idx === line.length) {
            idx = 0;
            line = content[++contentIndex] + '\n';
            normalized.push(lineHighlight);
            lineHighlight = {
              contentIndex,
              startIndex: idx,
            };
            continue;
          }
          idx++;
          j++;
        }
        lineHighlight.endIndex = idx;
        normalized.push(lineHighlight);
      }
      return normalized;
    },

    /**
     * If a group is an addition or a removal, break it down into smaller groups
     * of that type using the MAX_GROUP_SIZE. If the group is a shared section
     * or a delta it is returned as the single element of the result array.
     * @param {!Object} group A raw chunk from a diff response.
     * @return {!Array<!Array<!Object>>}
     */
    _breakdownGroup(group) {
      let key = null;
      if (group.a && !group.b) {
        key = 'a';
      } else if (group.b && !group.a) {
        key = 'b';
      } else if (group.ab) {
        key = 'ab';
      }

      if (!key) { return [group]; }

      return this._breakdown(group[key], MAX_GROUP_SIZE)
          .map(subgroupLines => {
            const subGroup = {};
            subGroup[key] = subgroupLines;
            if (group.due_to_rebase) {
              subGroup.due_to_rebase = true;
            }
            return subGroup;
          });
    },

    /**
     * Given an array and a size, return an array of arrays where no inner array
     * is larger than that size, preserving the original order.
     * @param {!Array<T>} array
     * @param {number} size
     * @return {!Array<!Array<T>>}
     * @template T
     */
    _breakdown(array, size) {
      if (!array.length) { return []; }
      if (array.length < size) { return [array]; }

      const head = array.slice(0, array.length - size);
      const tail = array.slice(array.length - size);

      return this._breakdown(head, size).concat([tail]);
    },
  });
})();
