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

  Polymer({
    is: 'gr-diff',

    /**
     * Fired when the diff is rendered.
     *
     * @event render
     */

    properties: {
      availablePatches: Array,
      changeNum: String,
      /*
       * A single object to encompass basePatchNum and patchNum is used
       * so that both can be set at once without incremental observers
       * firing after each property changes.
       */
      patchRange: Object,
      path: String,
      prefs: {
        type: Object,
        notify: true,
      },
      projectConfig: Object,

      _prefsReady: {
        type: Object,
        readOnly: true,
        value: function() {
          return new Promise(function(resolve) {
            this._resolvePrefsReady = resolve;
          }.bind(this));
        },
      },
      _baseComments: Array,
      _comments: Array,
      _drafts: Array,
      _baseDrafts: Array,
      /**
       * Base (left side) comments and drafts grouped by line number.
       * Only used for initial rendering.
       */
      _groupedBaseComments: {
        type: Object,
        value: function() { return {}; },
      },
      /**
       * Comments and drafts (right side) grouped by line number.
       * Only used for initial rendering.
       */
      _groupedComments: {
        type: Object,
        value: function() { return {}; },
      },
      _diffResponse: Object,
      _diff: {
        type: Object,
        value: function() { return {}; },
      },
      _loggedIn: {
        type: Boolean,
        value: false,
      },
      _initialRenderComplete: {
        type: Boolean,
        value: false,
      },
      _loading: {
        type: Boolean,
        value: true,
      },
      _savedPrefs: Object,

      _diffRequestsPromise: Object,  // Used for testing.
      _diffPreferencesPromise: Object,  // Used for testing.
    },

    observers: [
      '_prefsChanged(prefs.*)',
    ],

    ready: function() {
      app.accountReady.then(function() {
        this._loggedIn = app.loggedIn;
      }.bind(this));
    },

    scrollToLine: function(lineNum) {
      // TODO(andybons): Should this always be the right side?
      this.$.rightDiff.scrollToLine(lineNum);
    },

    scrollToNextDiffChunk: function() {
      this.$.rightDiff.scrollToNextDiffChunk();
    },

    scrollToPreviousDiffChunk: function() {
      this.$.rightDiff.scrollToPreviousDiffChunk();
    },

    scrollToNextCommentThread: function() {
      this.$.rightDiff.scrollToNextCommentThread();
    },

    scrollToPreviousCommentThread: function() {
      this.$.rightDiff.scrollToPreviousCommentThread();
    },

    reload: function() {
      this._loading = true;
      // If a diff takes a considerable amount of time to render, the previous
      // diff can end up showing up while the DOM is constructed. Clear the
      // content on a reload to prevent this.
      this._diff = {
        leftSide: [],
        rightSide: [],
      };

      var diffLoaded = this._getDiff().then(function(diff) {
        this._diffResponse = diff;
      }.bind(this));

      var promises = [
        this._prefsReady,
        diffLoaded,
      ];

      return app.accountReady.then(function() {
        promises.push(this._getDiffComments().then(function(res) {
          this._baseComments = res.baseComments;
          this._comments = res.comments;
        }.bind(this)));

        if (!app.loggedIn) {
          this._baseDrafts = [];
          this._drafts = [];
        } else {
          promises.push(this._getDiffDrafts().then(function(res) {
            this._baseDrafts = res.baseComments;
            this._drafts = res.comments;
          }.bind(this)));
        }

        this._diffRequestsPromise = Promise.all(promises).then(function() {
          this._render();
          this._loading = false;
        }.bind(this)).catch(function(err) {
          this._loading = false;
          alert('Oops. Something went wrong. Check the console and bug the ' +
              'PolyGerrit team for assistance.');
          throw err;
        }.bind(this));
      }.bind(this));
    },

    _getDiff: function() {
      return this.$.restAPI.getDiff(
          this.changeNum,
          this.patchRange.basePatchNum,
          this.patchRange.patchNum,
          this.path);
    },

    _getDiffComments: function() {
      return this.$.restAPI.getDiffComments(
          this.changeNum,
          this.patchRange.basePatchNum,
          this.patchRange.patchNum,
          this.path);
    },

    _getDiffDrafts: function() {
      return this.$.restAPI.getDiffDrafts(
          this.changeNum,
          this.patchRange.basePatchNum,
          this.patchRange.patchNum,
          this.path);
    },

    showDiffPreferences: function() {
      this.$.prefsOverlay.open();
    },

    _prefsChanged: function(changeRecord) {
      if (this._initialRenderComplete) {
        this._render();
      }
      this._resolvePrefsReady(changeRecord.base);
    },

    _render: function() {
      this._groupCommentsAndDrafts();
      this._processContent();

      // Allow for the initial rendering to complete before firing the event.
      this.async(function() {
        this.fire('render', null, {bubbles: false});
      }.bind(this), 1);

      this._initialRenderComplete = true;
    },

    _handlePrefsTap: function(e) {
      e.preventDefault();

      // TODO(andybons): This is not supported in IE. Implement a polyfill.
      // NOTE: Object.assign is NOT automatically a deep copy. If prefs adds
      // an object as a value, it must be marked enumerable.
      this._savedPrefs = Object.assign({}, this.prefs);
      this.$.prefsOverlay.open();
    },

    _handlePrefsSave: function(e) {
      e.stopPropagation();
      var el = Polymer.dom(e).rootTarget;
      el.disabled = true;
      app.accountReady.then(function() {
        if (!this._loggedIn) {
          el.disabled = false;
          this.$.prefsOverlay.close();
          return;
        }
        this._saveDiffPreferences().then(function() {
          this.$.prefsOverlay.close();
          el.disabled = false;
        }.bind(this)).catch(function(err) {
          el.disabled = false;
          alert('Oops. Something went wrong. Check the console and bug the ' +
                'PolyGerrit team for assistance.');
          throw err;
        });
      }.bind(this));
    },

    _saveDiffPreferences: function() {
      var xhr = document.createElement('gr-request');
      this._diffPreferencesPromise = xhr.send({
        method: 'PUT',
        url: '/accounts/self/preferences.diff',
        body: this.prefs,
      });
      return this._diffPreferencesPromise;
    },

    _handlePrefsCancel: function(e) {
      e.stopPropagation();
      this.prefs = this._savedPrefs;
      this.$.prefsOverlay.close();
    },

    _handleExpandContext: function(e) {
      var ctx = e.detail.context;
      var contextControlIndex = -1;
      for (var i = ctx.start; i <= ctx.end; i++) {
        this._diff.leftSide[i].hidden = false;
        this._diff.rightSide[i].hidden = false;
        if (this._diff.leftSide[i].type == 'CONTEXT_CONTROL' &&
            this._diff.rightSide[i].type == 'CONTEXT_CONTROL') {
          contextControlIndex = i;
        }
      }
      this._diff.leftSide[contextControlIndex].hidden = true;
      this._diff.rightSide[contextControlIndex].hidden = true;

      this.$.leftDiff.hideElementsWithIndex(contextControlIndex);
      this.$.rightDiff.hideElementsWithIndex(contextControlIndex);

      this.$.leftDiff.renderLineIndexRange(ctx.start, ctx.end);
      this.$.rightDiff.renderLineIndexRange(ctx.start, ctx.end);
    },

    _handleThreadHeightChange: function(e) {
      var index = e.detail.index;
      var diffEl = Polymer.dom(e).rootTarget;
      var otherSide = diffEl == this.$.leftDiff ?
          this.$.rightDiff : this.$.leftDiff;

      var threadHeight = e.detail.height;
      var otherSideHeight;
      if (otherSide.content[index].type == 'COMMENT_THREAD') {
        otherSideHeight = otherSide.getRowNaturalHeight(index);
      } else {
        otherSideHeight = otherSide.getRowHeight(index);
      }
      var maxHeight = Math.max(threadHeight, otherSideHeight);
      this.$.leftDiff.setRowHeight(index, maxHeight);
      this.$.rightDiff.setRowHeight(index, maxHeight);
    },

    _handleAddDraft: function(e) {
      var insertIndex = e.detail.index + 1;
      var diffEl = Polymer.dom(e).rootTarget;
      var content = diffEl.content;
      if (content[insertIndex] &&
          content[insertIndex].type == 'COMMENT_THREAD') {
        // A thread is already here. Do nothing.
        return;
      }
      var comment = {
        type: 'COMMENT_THREAD',
        comments: [{
          __draft: true,
          __draftID: Math.random().toString(36),
          line: e.detail.line,
          path: this.path,
        }]
      };
      if (diffEl == this.$.leftDiff &&
          this.patchRange.basePatchNum == 'PARENT') {
        comment.comments[0].side = 'PARENT';
        comment.patchNum = this.patchRange.patchNum;
      }

      if (content[insertIndex] &&
          content[insertIndex].type == 'FILLER') {
        content[insertIndex] = comment;
        diffEl.rowUpdated(insertIndex);
      } else {
        content.splice(insertIndex, 0, comment);
        diffEl.rowInserted(insertIndex);
      }

      var otherSide = diffEl == this.$.leftDiff ?
          this.$.rightDiff : this.$.leftDiff;
      if (otherSide.content[insertIndex] == null ||
          otherSide.content[insertIndex].type != 'COMMENT_THREAD') {
        otherSide.content.splice(insertIndex, 0, {
          type: 'FILLER',
        });
        otherSide.rowInserted(insertIndex);
      }
    },

    _handleRemoveThread: function(e) {
      var diffEl = Polymer.dom(e).rootTarget;
      var otherSide = diffEl == this.$.leftDiff ?
          this.$.rightDiff : this.$.leftDiff;
      var index = e.detail.index;

      if (otherSide.content[index].type == 'FILLER') {
        otherSide.content.splice(index, 1);
        otherSide.rowRemoved(index);
        diffEl.content.splice(index, 1);
        diffEl.rowRemoved(index);
      } else if (otherSide.content[index].type == 'COMMENT_THREAD') {
        diffEl.content[index] = {type: 'FILLER'};
        diffEl.rowUpdated(index);
        var height = otherSide.setRowNaturalHeight(index);
        diffEl.setRowHeight(index, height);
      } else {
        throw Error('A thread cannot be opposite anything but filler or ' +
            'another thread');
      }
    },

    _processContent: function() {
      var leftSide = [];
      var rightSide = [];
      var initialLineNum = 0 + (this._diffResponse.content.skip || 0);
      var ctx = {
        hidingLines: false,
        lastNumLinesHidden: 0,
        left: {
          lineNum: initialLineNum,
        },
        right: {
          lineNum: initialLineNum,
        }
      };
      var content = this._breakUpCommonChunksWithComments(ctx,
          this._diffResponse.content);
      var context = this.prefs.context;
      if (context == -1) {
        // Show the entire file.
        context = Infinity;
      }
      for (var i = 0; i < content.length; i++) {
        if (i == 0) {
          ctx.skipRange = [0, context];
        } else if (i == content.length - 1) {
          ctx.skipRange = [context, 0];
        } else {
          ctx.skipRange = [context, context];
        }
        ctx.diffChunkIndex = i;
        this._addDiffChunk(ctx, content[i], leftSide, rightSide);
      }

      this._diff = {
        leftSide: leftSide,
        rightSide: rightSide,
      };
    },

    // In order to show comments out of the bounds of the selected context,
    // treat them as diffs within the model so that the content (and context
    // surrounding it) renders correctly.
    _breakUpCommonChunksWithComments: function(ctx, content) {
      var result = [];
      var leftLineNum = ctx.left.lineNum;
      var rightLineNum = ctx.right.lineNum;
      for (var i = 0; i < content.length; i++) {
        if (!content[i].ab) {
          result.push(content[i]);
          if (content[i].a) {
            leftLineNum += content[i].a.length;
          }
          if (content[i].b) {
            rightLineNum += content[i].b.length;
          }
          continue;
        }
        var chunk = content[i].ab;
        var currentChunk = {ab: []};
        for (var j = 0; j < chunk.length; j++) {
          leftLineNum++;
          rightLineNum++;
          if (this._groupedBaseComments[leftLineNum] == null &&
              this._groupedComments[rightLineNum] == null) {
            currentChunk.ab.push(chunk[j]);
          } else {
            if (currentChunk.ab && currentChunk.ab.length > 0) {
              result.push(currentChunk);
              currentChunk = {ab: []};
            }
            // Append an annotation to indicate that this line should not be
            // highlighted even though it's implied with both `a` and `b`
            // defined. This is needed since there may be two lines that
            // should be highlighted but are equal (blank lines, for example).
            result.push({
              __noHighlight: true,
              a: [chunk[j]],
              b: [chunk[j]],
            });
          }
        }
        if (currentChunk.ab != null && currentChunk.ab.length > 0) {
          result.push(currentChunk);
        }
      }
      return result;
    },

    _groupCommentsAndDrafts: function() {
      this._baseDrafts.forEach(function(d) { d.__draft = true; });
      this._drafts.forEach(function(d) { d.__draft = true; });
      var allLeft = this._baseComments.concat(this._baseDrafts);
      var allRight = this._comments.concat(this._drafts);

      var leftByLine = {};
      var rightByLine = {};
      var mapFunc = function(byLine) {
        return function(c) {
          // File comments/drafts are grouped with line 1 for now.
          var line = c.line || 1;
          if (byLine[line] == null) {
            byLine[line] = [];
          }
          byLine[line].push(c);
        };
      };
      allLeft.forEach(mapFunc(leftByLine));
      allRight.forEach(mapFunc(rightByLine));

      this._groupedBaseComments = leftByLine;
      this._groupedComments = rightByLine;
    },

    _addContextControl: function(ctx, leftSide, rightSide) {
      var numLinesHidden = ctx.lastNumLinesHidden;
      var leftStart = leftSide.length - numLinesHidden;
      var leftEnd = leftSide.length;
      var rightStart = rightSide.length - numLinesHidden;
      var rightEnd = rightSide.length;
      if (leftStart != rightStart || leftEnd != rightEnd) {
        throw Error(
            'Left and right ranges for context control should be equal:' +
            'Left: [' + leftStart + ', ' + leftEnd + '] ' +
            'Right: [' + rightStart + ', ' + rightEnd + ']');
      }
      var obj = {
        type: 'CONTEXT_CONTROL',
        numLines: numLinesHidden,
        start: leftStart,
        end: leftEnd,
      };
      // NOTE: Be careful, here. This object is meant to be immutable. If the
      // object is altered within one side's array it will reflect the
      // alterations in another.
      leftSide.push(obj);
      rightSide.push(obj);
    },

    _addCommonDiffChunk: function(ctx, chunk, leftSide, rightSide) {
      for (var i = 0; i < chunk.ab.length; i++) {
        var numLines = Math.ceil(
            this._visibleLineLength(chunk.ab[i]) / this.prefs.line_length);
        var hidden = i >= ctx.skipRange[0] &&
            i < chunk.ab.length - ctx.skipRange[1];
        if (ctx.hidingLines && hidden == false) {
          // No longer hiding lines. Add a context control.
          this._addContextControl(ctx, leftSide, rightSide);
          ctx.lastNumLinesHidden = 0;
        }
        ctx.hidingLines = hidden;
        if (hidden) {
          ctx.lastNumLinesHidden++;
        }

        // Blank lines within a diff content array indicate a newline.
        leftSide.push({
          type: 'CODE',
          hidden: hidden,
          content: chunk.ab[i] || '\n',
          numLines: numLines,
          lineNum: ++ctx.left.lineNum,
        });
        rightSide.push({
          type: 'CODE',
          hidden: hidden,
          content: chunk.ab[i] || '\n',
          numLines: numLines,
          lineNum: ++ctx.right.lineNum,
        });

        this._addCommentsIfPresent(ctx, leftSide, rightSide);
      }
      if (ctx.lastNumLinesHidden > 0) {
        this._addContextControl(ctx, leftSide, rightSide);
      }
    },

    _addDiffChunk: function(ctx, chunk, leftSide, rightSide) {
      if (chunk.ab) {
        this._addCommonDiffChunk(ctx, chunk, leftSide, rightSide);
        return;
      }

      var leftHighlights = [];
      if (chunk.edit_a) {
        leftHighlights =
            this._normalizeIntralineHighlights(chunk.a, chunk.edit_a);
      }
      var rightHighlights = [];
      if (chunk.edit_b) {
        rightHighlights =
            this._normalizeIntralineHighlights(chunk.b, chunk.edit_b);
      }

      var aLen = (chunk.a && chunk.a.length) || 0;
      var bLen = (chunk.b && chunk.b.length) || 0;
      var maxLen = Math.max(aLen, bLen);
      for (var i = 0; i < maxLen; i++) {
        var hasLeftContent = chunk.a && i < chunk.a.length;
        var hasRightContent = chunk.b && i < chunk.b.length;
        var leftContent = hasLeftContent ? chunk.a[i] : '';
        var rightContent = hasRightContent ? chunk.b[i] : '';
        var highlight = !chunk.__noHighlight;
        var maxNumLines = this._maxLinesSpanned(leftContent, rightContent);
        if (hasLeftContent) {
          leftSide.push({
            type: 'CODE',
            content: leftContent || '\n',
            numLines: maxNumLines,
            lineNum: ++ctx.left.lineNum,
            highlight: highlight,
            intraline: highlight && leftHighlights.filter(function(hl) {
              return hl.contentIndex == i;
            }),
          });
        } else {
          leftSide.push({
            type: 'FILLER',
            numLines: maxNumLines,
          });
        }
        if (hasRightContent) {
          rightSide.push({
            type: 'CODE',
            content: rightContent || '\n',
            numLines: maxNumLines,
            lineNum: ++ctx.right.lineNum,
            highlight: highlight,
            intraline: highlight && rightHighlights.filter(function(hl) {
              return hl.contentIndex == i;
            }),
          });
        } else {
          rightSide.push({
            type: 'FILLER',
            numLines: maxNumLines,
          });
        }
        this._addCommentsIfPresent(ctx, leftSide, rightSide);
      }
    },

    _addCommentsIfPresent: function(ctx, leftSide, rightSide) {
      var leftComments = this._groupedBaseComments[ctx.left.lineNum];
      var rightComments = this._groupedComments[ctx.right.lineNum];
      if (leftComments) {
        var thread = {
          type: 'COMMENT_THREAD',
          comments: leftComments,
        };
        if (this.patchRange.basePatchNum == 'PARENT') {
          thread.patchNum = this.patchRange.patchNum;
        }
        leftSide.push(thread);
      }
      if (rightComments) {
        rightSide.push({
          type: 'COMMENT_THREAD',
          comments: rightComments,
        });
      }
      if (leftComments && !rightComments) {
        rightSide.push({type: 'FILLER'});
      } else if (!leftComments && rightComments) {
        leftSide.push({type: 'FILLER'});
      }
      this._groupedBaseComments[ctx.left.lineNum] = null;
      this._groupedComments[ctx.right.lineNum] = null;
    },

    // 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: function(content, highlights) {
      var contentIndex = 0;
      var idx = 0;
      var normalized = [];
      for (var i = 0; i < highlights.length; i++) {
        var line = content[contentIndex] + '\n';
        var hl = highlights[i];
        var j = 0;
        while (j < hl[0]) {
          if (idx == line.length) {
            idx = 0;
            line = content[++contentIndex] + '\n';
            continue;
          }
          idx++;
          j++;
        }
        var lineHighlight = {
          contentIndex: 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: contentIndex,
              startIndex: idx,
            };
            continue;
          }
          idx++;
          j++;
        }
        lineHighlight.endIndex = idx;
        normalized.push(lineHighlight);
      }
      return normalized;
    },

    _visibleLineLength: function(contents) {
      // http://jsperf.com/performance-of-match-vs-split
      var numTabs = contents.split('\t').length - 1;
      return contents.length - numTabs + (this.prefs.tab_size * numTabs);
    },

    _maxLinesSpanned: function(left, right) {
      return Math.max(
          Math.ceil(this._visibleLineLength(left) / this.prefs.line_length),
          Math.ceil(this._visibleLineLength(right) / this.prefs.line_length));
    },
  });
})();
