// 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(window, GrDiffGroup, GrDiffLine) {
  'use strict';

  function GrDiffBuilder(diff, comments, prefs, outputEl) {
    this._diff = diff;
    this._comments = comments;
    this._prefs = prefs;
    this._outputEl = outputEl;
    this._groups = [];

    this._commentLocations = this._getCommentLocations(comments);
    this._processContent(diff.content, this._groups, prefs.context);
  }

  GrDiffBuilder.LESS_THAN_CODE = '<'.charCodeAt(0);
  GrDiffBuilder.GREATER_THAN_CODE = '>'.charCodeAt(0);
  GrDiffBuilder.AMPERSAND_CODE = '&'.charCodeAt(0);
  GrDiffBuilder.SEMICOLON_CODE = ';'.charCodeAt(0);

  GrDiffBuilder.TAB_REGEX = /\t/g;

  GrDiffBuilder.LINE_FEED_HTML =
      '<span class="style-scope gr-diff br"></span>';

  GrDiffBuilder.GroupType = {
    ADDED: 'b',
    BOTH: 'ab',
    REMOVED: 'a',
  };

  GrDiffBuilder.Highlights = {
    ADDED: 'edit_b',
    REMOVED: 'edit_a',
  };

  GrDiffBuilder.Side = {
    LEFT: 'left',
    RIGHT: 'right',
  };

  GrDiffBuilder.ContextButtonType = {
    ABOVE: 'above',
    BELOW: 'below',
    ALL: 'all',
  };

  var PARTIAL_CONTEXT_AMOUNT = 10;

  GrDiffBuilder.prototype.emitDiff = function() {
    for (var i = 0; i < this._groups.length; i++) {
      this.emitGroup(this._groups[i]);
    }
  };

  GrDiffBuilder.prototype.buildSectionElement = function(
      group, opt_beforeSection) {
    throw Error('Subclasses must implement buildGroupElement');
  };

  GrDiffBuilder.prototype.emitGroup = function(group, opt_beforeSection) {
    var element = this.buildSectionElement(group);
    this._outputEl.insertBefore(element, opt_beforeSection);
    group.element = element;
  };

  GrDiffBuilder.prototype.renderSection = function(element) {
    for (var i = 0; i < this._groups.length; i++) {
      var group = this._groups[i];
      if (group.element === element) {
        var newElement = this.buildSectionElement(group);
        group.element.parentElement.replaceChild(newElement, group.element);
        group.element = newElement;
        break;
      }
    }
  };

  GrDiffBuilder.prototype.getSectionsByLineRange = function(
      startLine, endLine, opt_side) {
    var sections = [];
    for (var i = 0; i < this._groups.length; i++) {
      var group = this._groups[i];
      if (group.lines.length === 0) {
        continue;
      }
      var groupStartLine;
      var groupEndLine;
      if (opt_side === GrDiffBuilder.Side.LEFT) {
        groupStartLine = group.lines[0].beforeNumber;
        groupEndLine = group.lines[group.lines.length - 1].beforeNumber;
      } else if (opt_side === GrDiffBuilder.Side.RIGHT) {
        groupStartLine = group.lines[0].afterNumber;
        groupEndLine = group.lines[group.lines.length - 1].afterNumber;
      }
      if (startLine <= groupEndLine && endLine >= groupStartLine) {
        sections.push(group.element);
      }
    }
    return sections;
  };

  GrDiffBuilder.prototype._processContent = function(content, groups, context) {
    this._appendFileComments(groups);

    var WHOLE_FILE = -1;
    context = content.length > 1 ? context : WHOLE_FILE;

    var lineNums = {
      left: 0,
      right: 0,
    };
    content = this._splitCommonGroupsWithComments(content, lineNums);
    for (var i = 0; i < content.length; i++) {
      var group = content[i];
      var lines = [];

      if (group[GrDiffBuilder.GroupType.BOTH] !== undefined) {
        var rows = group[GrDiffBuilder.GroupType.BOTH];
        this._appendCommonLines(rows, lines, lineNums);

        var hiddenRange = [context, rows.length - context];
        if (i === 0) {
          hiddenRange[0] = 0;
        } else if (i === content.length - 1) {
          hiddenRange[1] = rows.length;
        }

        if (context !== WHOLE_FILE && hiddenRange[1] - hiddenRange[0] > 0) {
          this._insertContextGroups(groups, lines, hiddenRange);
        } else {
          groups.push(new GrDiffGroup(GrDiffGroup.Type.BOTH, lines));
        }
        continue;
      }

      if (group[GrDiffBuilder.GroupType.REMOVED] !== undefined) {
        var highlights = undefined;
        if (group[GrDiffBuilder.Highlights.REMOVED] !== undefined) {
          highlights = this._normalizeIntralineHighlights(
              group[GrDiffBuilder.GroupType.REMOVED],
              group[GrDiffBuilder.Highlights.REMOVED]);
        }
        this._appendRemovedLines(group[GrDiffBuilder.GroupType.REMOVED], lines,
            lineNums, highlights);
      }

      if (group[GrDiffBuilder.GroupType.ADDED] !== undefined) {
        var highlights = undefined;
        if (group[GrDiffBuilder.Highlights.ADDED] !== undefined) {
          highlights = this._normalizeIntralineHighlights(
            group[GrDiffBuilder.GroupType.ADDED],
            group[GrDiffBuilder.Highlights.ADDED]);
        }
        this._appendAddedLines(group[GrDiffBuilder.GroupType.ADDED], lines,
            lineNums, highlights);
      }
      groups.push(new GrDiffGroup(GrDiffGroup.Type.DELTA, lines));
    }
  };

  GrDiffBuilder.prototype._appendFileComments = function(groups) {
    var line = new GrDiffLine(GrDiffLine.Type.BOTH);
    line.beforeNumber = GrDiffLine.FILE;
    line.afterNumber = GrDiffLine.FILE;
    groups.push(new GrDiffGroup(GrDiffGroup.Type.BOTH, [line]));
  };

  GrDiffBuilder.prototype._getCommentLocations = function(comments) {
    var result = {
      left: {},
      right: {},
    };
    for (var side in comments) {
      if (side !== GrDiffBuilder.Side.LEFT &&
          side !== GrDiffBuilder.Side.RIGHT) {
        continue;
      }
      comments[side].forEach(function(c) {
        result[side][c.line || GrDiffLine.FILE] = true;
      });
    }
    return result;
  };

  GrDiffBuilder.prototype._commentIsAtLineNum = function(side, lineNum) {
    return this._commentLocations[side][lineNum] === true;
  };

  // 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.
  GrDiffBuilder.prototype._splitCommonGroupsWithComments = function(content,
      lineNums) {
    var result = [];
    var leftLineNum = lineNums.left;
    var rightLineNum = lineNums.right;
    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._commentIsAtLineNum(GrDiffBuilder.Side.LEFT, leftLineNum) ||
            this._commentIsAtLineNum(GrDiffBuilder.Side.RIGHT, rightLineNum)) {
          if (currentChunk.ab && currentChunk.ab.length > 0) {
            result.push(currentChunk);
            currentChunk = {ab: []};
          }
          result.push({ab: [chunk[j]]});
        } else {
          currentChunk.ab.push(chunk[j]);
        }
      }
      // != instead of !== because we want to cover both undefined and null.
      if (currentChunk.ab != null && currentChunk.ab.length > 0) {
        result.push(currentChunk);
      }
    }
    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.
  GrDiffBuilder.prototype._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;
  };

  GrDiffBuilder.prototype._insertContextGroups = function(groups, lines,
      hiddenRange) {
    var linesBeforeCtx = lines.slice(0, hiddenRange[0]);
    var hiddenLines = lines.slice(hiddenRange[0], hiddenRange[1]);
    var linesAfterCtx = lines.slice(hiddenRange[1]);

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

    var ctxLine = new GrDiffLine(GrDiffLine.Type.CONTEXT_CONTROL);
    ctxLine.contextGroup =
        new GrDiffGroup(GrDiffGroup.Type.BOTH, hiddenLines);
    groups.push(new GrDiffGroup(GrDiffGroup.Type.CONTEXT_CONTROL,
        [ctxLine]));

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

  GrDiffBuilder.prototype._appendCommonLines = function(rows, lines, lineNums) {
    for (var i = 0; i < rows.length; i++) {
      var line = new GrDiffLine(GrDiffLine.Type.BOTH);
      line.text = rows[i];
      line.beforeNumber = ++lineNums.left;
      line.afterNumber = ++lineNums.right;
      lines.push(line);
    }
  };

  GrDiffBuilder.prototype._appendRemovedLines = function(rows, lines, lineNums,
      opt_highlights) {
    for (var i = 0; i < rows.length; i++) {
      var line = new GrDiffLine(GrDiffLine.Type.REMOVE);
      line.text = rows[i];
      line.beforeNumber = ++lineNums.left;
      if (opt_highlights) {
        line.highlights = opt_highlights.filter(function(hl) {
          return hl.contentIndex === i;
        });
      }
      lines.push(line);
    }
  };

  GrDiffBuilder.prototype._appendAddedLines = function(rows, lines, lineNums,
      opt_highlights) {
    for (var i = 0; i < rows.length; i++) {
      var line = new GrDiffLine(GrDiffLine.Type.ADD);
      line.text = rows[i];
      line.afterNumber = ++lineNums.right;
      if (opt_highlights) {
        line.highlights = opt_highlights.filter(function(hl) {
          return hl.contentIndex === i;
        });
      }
      lines.push(line);
    }
  };

  GrDiffBuilder.prototype._createContextControl = function(section, line) {
    if (!line.contextGroup || !line.contextGroup.lines.length) {
      return null;
    }

    var td = this._createElement('td');
    var showPartialLinks =
        line.contextGroup.lines.length > PARTIAL_CONTEXT_AMOUNT;

    if (showPartialLinks) {
      td.appendChild(this._createContextButton(
          GrDiffBuilder.ContextButtonType.ABOVE, section, line));
      td.appendChild(document.createTextNode(' - '));
    }

    td.appendChild(this._createContextButton(
        GrDiffBuilder.ContextButtonType.ALL, section, line));

    if (showPartialLinks) {
      td.appendChild(document.createTextNode(' - '));
      td.appendChild(this._createContextButton(
          GrDiffBuilder.ContextButtonType.BELOW, section, line));
    }

    return td;
  };

  GrDiffBuilder.prototype._createContextButton = function(type, section, line) {
    var contextLines = line.contextGroup.lines;
    var context = PARTIAL_CONTEXT_AMOUNT;

    var button = this._createElement('gr-button', 'showContext');
    button.setAttribute('link', true);

    var text;
    var groups = []; // The groups that replace this one if tapped.

    if (type === GrDiffBuilder.ContextButtonType.ALL) {
      text = 'Show ' + contextLines.length + ' common line';
      if (contextLines.length > 1) { text += 's'; }
      groups.push(line.contextGroup);
    } else if (type === GrDiffBuilder.ContextButtonType.ABOVE) {
      text = '+' + context + '↑';
      this._insertContextGroups(groups, contextLines,
          [context, contextLines.length]);
    } else if (type === GrDiffBuilder.ContextButtonType.BELOW) {
      text = '+' + context + '↓';
      this._insertContextGroups(groups, contextLines,
          [0, contextLines.length - context]);
    }

    button.textContent = text;

    button.addEventListener('tap', function(e) {
      e.detail = {
        groups: groups,
        section: section,
      };
      // Let it bubble up the DOM tree.
    });

    return button;
  };

  GrDiffBuilder.prototype._getCommentsForLine = function(comments, line,
      opt_side) {
    function byLineNum(lineNum) {
      return function(c) {
        return (c.line === lineNum) ||
               (c.line === undefined && lineNum === GrDiffLine.FILE);
      };
    }
    var leftComments =
        comments[GrDiffBuilder.Side.LEFT].filter(byLineNum(line.beforeNumber));
    var rightComments =
        comments[GrDiffBuilder.Side.RIGHT].filter(byLineNum(line.afterNumber));

    var result;

    switch (opt_side) {
      case GrDiffBuilder.Side.LEFT:
        result = leftComments;
        break;
      case GrDiffBuilder.Side.RIGHT:
        result = rightComments;
        break;
      default:
        result = leftComments.concat(rightComments);
        break;
    }

    return result;
  };

  GrDiffBuilder.prototype.createCommentThread = function(changeNum, patchNum,
      path, side, projectConfig) {
    var threadEl = document.createElement('gr-diff-comment-thread');
    threadEl.changeNum = changeNum;
    threadEl.patchNum = patchNum;
    threadEl.path = path;
    threadEl.side = side;
    threadEl.projectConfig = projectConfig;
    return threadEl;
  };

  GrDiffBuilder.prototype._commentThreadForLine = function(line, opt_side) {
    var comments = this._getCommentsForLine(this._comments, line, opt_side);
    if (!comments || comments.length === 0) {
      return null;
    }

    var patchNum = this._comments.meta.patchRange.patchNum;
    var side = comments[0].side || 'REVISION';
    if (line.type === GrDiffLine.Type.REMOVE ||
        opt_side === GrDiffBuilder.Side.LEFT) {
      if (this._comments.meta.patchRange.basePatchNum === 'PARENT') {
        side = 'PARENT';
      } else {
        patchNum = this._comments.meta.patchRange.basePatchNum;
      }
    }
    var threadEl = this.createCommentThread(
        this._comments.meta.changeNum,
        patchNum,
        this._comments.meta.path,
        side,
        this._comments.meta.projectConfig);
    threadEl.comments = comments;
    return threadEl;
  };

  GrDiffBuilder.prototype._createLineEl = function(line, number, type,
      opt_class) {
    var td = this._createElement('td');
    if (opt_class) {
      td.classList.add(opt_class);
    }
    if (line.type === GrDiffLine.Type.BLANK) {
      return td;
    } else if (line.type === GrDiffLine.Type.CONTEXT_CONTROL) {
      td.classList.add('contextLineNum');
      td.setAttribute('data-value', '@@');
    } else if (line.type === GrDiffLine.Type.BOTH || line.type === type) {
      td.classList.add('lineNum');
      td.setAttribute('data-value', number);
    }
    return td;
  };

  GrDiffBuilder.prototype._createTextEl = function(line) {
    var td = this._createElement('td');
    if (line.type !== GrDiffLine.Type.BLANK) {
      td.classList.add('content');
    }
    td.classList.add(line.type);
    var text = line.text;
    var html = util.escapeHTML(text);

    td.classList.add(line.highlights.length > 0 ?
        'lightHighlight' : 'darkHighlight');

    if (line.highlights.length > 0) {
      html = this._addIntralineHighlights(text, html, line.highlights);
    }

    if (this._textLength(text, this._prefs.tab_size) >
        this._prefs.line_length) {
      html = this._addNewlines(text, html);
    }
    html = this._addTabWrappers(html);

    // If the html is equivalent to the text then it didn't get highlighted
    // or escaped. Use textContent which is faster than innerHTML.
    if (html === text) {
      td.textContent = text;
    } else {
      td.innerHTML = html;
    }
    return td;
  };

  GrDiffBuilder.prototype._textLength = function(text, tabSize) {
    // TODO(andybons): Unicode support.
    var numChars = 0;
    for (var i = 0; i < text.length; i++) {
      if (text[i] === '\t') {
        numChars += tabSize;
      } else {
        numChars++;
      }
    }
    return numChars;
  };

  // Advance `index` by the appropriate number of characters that would
  // represent one source code character and return that index. For
  // example, for source code '<span>' the escaped html string is
  // '&lt;span&gt;'. Advancing from index 0 on the prior html string would
  // return 4, since &lt; maps to one source code character ('<').
  GrDiffBuilder.prototype._advanceChar = function(html, index) {
    // TODO(andybons): Unicode is all kinds of messed up in JS. Account for it.
    // https://mathiasbynens.be/notes/javascript-unicode

    // Tags don't count as characters
    while (index < html.length &&
           html.charCodeAt(index) === GrDiffBuilder.LESS_THAN_CODE) {
      while (index < html.length &&
             html.charCodeAt(index) !== GrDiffBuilder.GREATER_THAN_CODE) {
        index++;
      }
      index++;  // skip the ">" itself
    }
    // An HTML entity (e.g., &lt;) counts as one character.
    if (index < html.length &&
        html.charCodeAt(index) === GrDiffBuilder.AMPERSAND_CODE) {
      while (index < html.length &&
             html.charCodeAt(index) !== GrDiffBuilder.SEMICOLON_CODE) {
        index++;
      }
    }
    return index + 1;
  };

  GrDiffBuilder.prototype._addNewlines = function(text, html) {
    var htmlIndex = 0;
    var indices = [];
    var numChars = 0;
    for (var i = 0; i < text.length; i++) {
      if (numChars > 0 && numChars % this._prefs.line_length === 0) {
        indices.push(htmlIndex);
      }
      htmlIndex = this._advanceChar(html, htmlIndex);
      if (text[i] === '\t') {
        numChars += this._prefs.tab_size;
      } else {
        numChars++;
      }
    }
    var result = html;
    // Since the result string is being altered in place, start from the end
    // of the string so that the insertion indices are not affected as the
    // result string changes.
    for (var i = indices.length - 1; i >= 0; i--) {
      result = result.slice(0, indices[i]) + GrDiffBuilder.LINE_FEED_HTML +
          result.slice(indices[i]);
    }
    return result;
  };

  GrDiffBuilder.prototype._addTabWrappers = function(html) {
    var htmlStr = this._getTabWrapper(this._prefs.tab_size,
        this._prefs.show_tabs);
    return html.replace(GrDiffBuilder.TAB_REGEX, htmlStr);
  };

  GrDiffBuilder.prototype._addIntralineHighlights = function(content, html,
      highlights) {
    var START_TAG = '<hl class="style-scope gr-diff">';
    var END_TAG = '</hl>';

    for (var i = 0; i < highlights.length; i++) {
      var hl = highlights[i];

      var htmlStartIndex = 0;
      // Find the index of the HTML string to insert the start tag.
      for (var j = 0; j < hl.startIndex; j++) {
        htmlStartIndex = this._advanceChar(html, htmlStartIndex);
      }

      var htmlEndIndex = 0;
      if (hl.endIndex !== undefined) {
        for (var j = 0; j < hl.endIndex; j++) {
          htmlEndIndex = this._advanceChar(html, htmlEndIndex);
        }
      } else {
        // If endIndex isn't present, continue to the end of the line.
        htmlEndIndex = html.length;
      }
      // The start and end indices could be the same if a highlight is meant
      // to start at the end of a line and continue onto the next one.
      // Ignore it.
      if (htmlStartIndex !== htmlEndIndex) {
        html = html.slice(0, htmlStartIndex) + START_TAG +
              html.slice(htmlStartIndex, htmlEndIndex) + END_TAG +
              html.slice(htmlEndIndex);
      }
    }
    return html;
  };

  GrDiffBuilder.prototype._getTabWrapper = function(tabSize, showTabs) {
    // Force this to be a number to prevent arbitrary injection.
    tabSize = +tabSize;
    if (isNaN(tabSize)) {
      throw Error('Invalid tab size from preferences.');
    }

    var str = '<span class="style-scope gr-diff tab ';
    if (showTabs) {
      str += 'withIndicator';
    }
    str += '" style="';
    // TODO(andybons): CSS tab-size is not supported in IE.
    str += 'tab-size:' + tabSize + ';';
    str += '-moz-tab-size:' + tabSize + ';';
    str += '">\t</span>';
    return str;
  };

  GrDiffBuilder.prototype._createElement = function(tagName, className) {
    var el = document.createElement(tagName);
    // When Shady DOM is being used, these classes are added to account for
    // Polymer's polyfill behavior. In order to guarantee sufficient
    // specificity within the CSS rules, these are added to every element.
    // Since the Polymer DOM utility functions (which would do this
    // automatically) are not being used for performance reasons, this is
    // done manually.
    el.classList.add('style-scope', 'gr-diff');
    if (!!className) {
      el.classList.add(className);
    }
    return el;
  };

  window.GrDiffBuilder = GrDiffBuilder;
})(window, GrDiffGroup, GrDiffLine);
