/**
 * @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.
 */
import {GrDiffLine} from '../gr-diff/gr-diff-line.js';
import {GrDiffGroup} from '../gr-diff/gr-diff-group.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';

/**
 * In JS, unicode code points above 0xFFFF occupy two elements of a string.
 * For example '𐀏'.length is 2. An occurence of such a code point is called a
 * surrogate pair.
 *
 * This regex segments a string along tabs ('\t') and surrogate pairs, since
 * these are two cases where '1 char' does not automatically imply '1 column'.
 *
 * TODO: For human languages whose orthographies use combining marks, this
 * approach won't correctly identify the grapheme boundaries. In those cases,
 * a grapheme consists of multiple code points that should count as only one
 * character against the column limit. Getting that correct (if it's desired)
 * is probably beyond the limits of a regex, but there are nonstandard APIs to
 * do this, and proposed (but, as of Nov 2017, unimplemented) standard APIs.
 *
 * Further reading:
 *   On Unicode in JS: https://mathiasbynens.be/notes/javascript-unicode
 *   Graphemes: http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
 *   A proposed JS API: https://github.com/tc39/proposal-intl-segmenter
 */
const REGEX_TAB_OR_SURROGATE_PAIR = /\t|[\uD800-\uDBFF][\uDC00-\uDFFF]/;

export function GrDiffBuilder(diff, prefs, outputEl, layers) {
  this._diff = diff;
  this._numLinesLeft = this._diff.content ? this._diff.content.reduce(
      (sum, chunk) => {
        const left = chunk.a || chunk.ab;
        return sum + (left ? left.length : 0);
      }, 0) : 0;
  this._prefs = prefs;
  this._outputEl = outputEl;
  this.groups = [];
  this._blameInfo = null;

  this.layers = layers || [];

  if (isNaN(prefs.tab_size) || prefs.tab_size <= 0) {
    throw Error('Invalid tab size from preferences.');
  }

  if (isNaN(prefs.line_length) || prefs.line_length <= 0) {
    throw Error('Invalid line length from preferences.');
  }

  for (const layer of this.layers) {
    if (layer.addListener) {
      layer.addListener(this._handleLayerUpdate.bind(this));
    }
  }
}

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

const PARTIAL_CONTEXT_AMOUNT = 10;

/**
 * Abstract method
 *
 * @param {string} outputEl
 * @param {number} fontSize
 */
GrDiffBuilder.prototype.addColumns = function() {
  throw Error('Subclasses must implement addColumns');
};

/**
 * Abstract method
 *
 * @param {Object} group
 */
GrDiffBuilder.prototype.buildSectionElement = function() {
  throw Error('Subclasses must implement buildSectionElement');
};

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

GrDiffBuilder.prototype.getGroupsByLineRange = function(
    startLine, endLine, opt_side) {
  const groups = [];
  for (let i = 0; i < this.groups.length; i++) {
    const group = this.groups[i];
    if (group.lines.length === 0) {
      continue;
    }
    let groupStartLine = 0;
    let groupEndLine = 0;
    if (opt_side) {
      groupStartLine = group.lineRange[opt_side].start;
      groupEndLine = group.lineRange[opt_side].end;
    }

    if (groupStartLine === 0) { // Line was removed or added.
      groupStartLine = groupEndLine;
    }
    if (groupEndLine === 0) { // Line was removed or added.
      groupEndLine = groupStartLine;
    }
    if (startLine <= groupEndLine && endLine >= groupStartLine) {
      groups.push(group);
    }
  }
  return groups;
};

GrDiffBuilder.prototype.getContentTdByLine = function(
    lineNumber, opt_side, opt_root) {
  const root = dom(opt_root || this._outputEl);
  const sideSelector = opt_side ? ('.' + opt_side) : '';
  return root.querySelector('td.lineNum[data-value="' + lineNumber +
    '"]' + sideSelector + ' ~ td.content');
};

GrDiffBuilder.prototype.getContentByLine = function(
    lineNumber, opt_side, opt_root) {
  return this.getContentTdByLine(lineNumber, opt_side, opt_root)
      .querySelector('.contentText');
};

/**
 * Find line elements or line objects by a range of line numbers and a side.
 *
 * @param {number} start The first line number
 * @param {number} end The last line number
 * @param {string} opt_side The side of the range. Either 'left' or 'right'.
 * @param {!Array<GrDiffLine>} out_lines The output list of line objects. Use
 *     null if not desired.
 * @param  {!Array<HTMLElement>} out_elements The output list of line elements.
 *     Use null if not desired.
 */
GrDiffBuilder.prototype.findLinesByRange = function(start, end, opt_side,
    out_lines, out_elements) {
  const groups = this.getGroupsByLineRange(start, end, opt_side);
  for (const group of groups) {
    let content = null;
    for (const line of group.lines) {
      if ((opt_side === 'left' && line.type === GrDiffLine.Type.ADD) ||
          (opt_side === 'right' && line.type === GrDiffLine.Type.REMOVE)) {
        continue;
      }
      const lineNumber = opt_side === 'left' ?
        line.beforeNumber : line.afterNumber;
      if (lineNumber < start || lineNumber > end) { continue; }

      if (out_lines) { out_lines.push(line); }
      if (out_elements) {
        if (content) {
          content = this._getNextContentOnSide(content, opt_side);
        } else {
          content = this.getContentByLine(lineNumber, opt_side,
              group.element);
        }
        if (content) { out_elements.push(content); }
      }
    }
  }
};

/**
 * Re-renders the DIV.contentText elements for the given side and range of
 * diff content.
 */
GrDiffBuilder.prototype._renderContentByRange = function(start, end, side) {
  const lines = [];
  const elements = [];
  let line;
  let el;
  this.findLinesByRange(start, end, side, lines, elements);
  for (let i = 0; i < lines.length; i++) {
    line = lines[i];
    el = elements[i];
    if (!el) {
      // Cannot re-render an element if it does not exist. This can happen
      // if lines are collapsed and not visible on the page yet.
      continue;
    }
    const lineNumberEl = this._getLineNumberEl(el, side);
    el.parentElement.replaceChild(
        this._createTextEl(lineNumberEl, line, side).firstChild,
        el);
  }
};

GrDiffBuilder.prototype.getSectionsByLineRange = function(
    startLine, endLine, opt_side) {
  return this.getGroupsByLineRange(startLine, endLine, opt_side).map(
      group => group.element);
};

GrDiffBuilder.prototype._createContextControl = function(section, line) {
  if (!line.contextGroups) return null;

  const leftStart = line.contextGroups[0].lineRange.left.start;
  const leftEnd =
      line.contextGroups[line.contextGroups.length - 1].lineRange.left.end;

  const numLines = leftEnd - leftStart + 1;

  if (numLines === 0) return null;

  const td = this._createElement('td');
  const showPartialLinks = numLines > PARTIAL_CONTEXT_AMOUNT;

  if (showPartialLinks && leftStart > 1) {
    td.appendChild(this._createContextButton(
        GrDiffBuilder.ContextButtonType.ABOVE, section, line, numLines));
  }

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

  if (showPartialLinks && leftEnd < this._numLinesLeft) {
    td.appendChild(this._createContextButton(
        GrDiffBuilder.ContextButtonType.BELOW, section, line, numLines));
  }

  return td;
};

GrDiffBuilder.prototype._createContextButton = function(type, section, line,
    numLines) {
  const context = PARTIAL_CONTEXT_AMOUNT;

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

  let text;
  let groups = []; // The groups that replace this one if tapped.
  if (type === GrDiffBuilder.ContextButtonType.ALL) {
    const icon = this._createElement('iron-icon', 'showContext');
    icon.setAttribute('icon', 'gr-icons:unfold-more');
    dom(button).appendChild(icon);

    text = 'Show ' + numLines + ' common line';
    if (numLines > 1) { text += 's'; }
    groups.push(...line.contextGroups);
  } else if (type === GrDiffBuilder.ContextButtonType.ABOVE) {
    text = '+' + context + ' above';
    groups = GrDiffGroup.hideInContextControl(line.contextGroups,
        context, numLines);
  } else if (type === GrDiffBuilder.ContextButtonType.BELOW) {
    text = '+' + context + ' below';
    groups = GrDiffGroup.hideInContextControl(line.contextGroups,
        0, numLines - context);
  }
  const textSpan = this._createElement('span', 'showContext');
  dom(textSpan).textContent = text;
  dom(button).appendChild(textSpan);

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

  return button;
};

GrDiffBuilder.prototype._createLineEl = function(
    line, number, type, side) {
  const td = this._createElement('td');
  if (line.type === GrDiffLine.Type.BLANK) {
    return td;
  }
  if (line.type === GrDiffLine.Type.CONTEXT_CONTROL) {
    td.classList.add('contextLineNum');
    return td;
  }

  if (line.type === GrDiffLine.Type.BOTH || line.type === type) {
    const button = this._createElement('button');
    button.tabIndex = -1;
    td.appendChild(button);

    // Both td and button need a number of classes/attributes for various
    // selectors to work.
    this._decorateLineEl(td, number, side);
    td.classList.add('lineNum');
    this._decorateLineEl(button, number, side);
    button.classList.add('lineNumButton');

    button.textContent = number === 'FILE' ? 'File' : number;

    // Add aria-labels for valid line numbers.
    // For unified diff, this method will be called with number set to 0 for
    // the empty line number column for added/removed lines. This should not
    // be announced to the screenreader.
    if (number > 0) {
      if (line.type === GrDiffLine.Type.REMOVE) {
        button.setAttribute('aria-label', `${number} removed`);
      } else if (line.type === GrDiffLine.Type.ADD) {
        button.setAttribute('aria-label', `${number} added`);
      }
    }
  }

  return td;
};

GrDiffBuilder.prototype._decorateLineEl = function(el, number, side) {
  el.classList.add(side);
  el.dataset.value = number;
};

GrDiffBuilder.prototype._createTextEl = function(
    lineNumberEl, line, opt_side) {
  const td = this._createElement('td');
  if (line.type !== GrDiffLine.Type.BLANK) {
    td.classList.add('content');
  }

  // If intraline info is not available, the entire line will be
  // considered as changed and marked as dark red / green color
  if (!line.hasIntralineInfo) {
    td.classList.add('no-intraline-info');
  }
  td.classList.add(line.type);

  if (line.beforeNumber !== 'FILE') {
    const lineLimit =
        !this._prefs.line_wrapping ? this._prefs.line_length : Infinity;
    const contentText =
        this._formatText(line.text, this._prefs.tab_size, lineLimit);

    if (opt_side) {
      contentText.setAttribute('data-side', opt_side);
    }

    for (const layer of this.layers) {
      if (typeof layer.annotate == 'function') {
        layer.annotate(contentText, lineNumberEl, line);
      }
    }

    td.appendChild(contentText);
  } else {
    td.classList.add('file');
  }

  return td;
};

/**
 * Returns a 'div' element containing the supplied |text| as its innerText,
 * with '\t' characters expanded to a width determined by |tabSize|, and the
 * text wrapped at column |lineLimit|, which may be Infinity if no wrapping is
 * desired.
 *
 * @param {string} text The text to be formatted.
 * @param {number} tabSize The width of each tab stop.
 * @param {number} lineLimit The column after which to wrap lines.
 * @return {HTMLElement}
 */
GrDiffBuilder.prototype._formatText = function(text, tabSize, lineLimit) {
  const contentText = this._createElement('div', 'contentText');

  let columnPos = 0;
  let textOffset = 0;
  for (const segment of text.split(REGEX_TAB_OR_SURROGATE_PAIR)) {
    if (segment) {
      // |segment| contains only normal characters. If |segment| doesn't fit
      // entirely on the current line, append chunks of |segment| followed by
      // line breaks.
      let rowStart = 0;
      let rowEnd = lineLimit - columnPos;
      while (rowEnd < segment.length) {
        contentText.appendChild(
            document.createTextNode(segment.substring(rowStart, rowEnd)));
        contentText.appendChild(this._createElement('span', 'br'));
        columnPos = 0;
        rowStart = rowEnd;
        rowEnd += lineLimit;
      }
      // Append the last part of |segment|, which fits on the current line.
      contentText.appendChild(
          document.createTextNode(segment.substring(rowStart)));
      columnPos += (segment.length - rowStart);
      textOffset += segment.length;
    }
    if (textOffset < text.length) {
      // Handle the special character at |textOffset|.
      if (text.startsWith('\t', textOffset)) {
        // Append a single '\t' character.
        let effectiveTabSize = tabSize - (columnPos % tabSize);
        if (columnPos + effectiveTabSize > lineLimit) {
          contentText.appendChild(this._createElement('span', 'br'));
          columnPos = 0;
          effectiveTabSize = tabSize;
        }
        contentText.appendChild(this._getTabWrapper(effectiveTabSize));
        columnPos += effectiveTabSize;
        textOffset++;
      } else {
        // Append a single surrogate pair.
        if (columnPos >= lineLimit) {
          contentText.appendChild(this._createElement('span', 'br'));
          columnPos = 0;
        }
        contentText.appendChild(document.createTextNode(
            text.substring(textOffset, textOffset + 2)));
        textOffset += 2;
        columnPos += 1;
      }
    }
  }
  return contentText;
};

/**
 * Returns a <span> element holding a '\t' character, that will visually
 * occupy |tabSize| many columns.
 *
 * @param {number} tabSize The effective size of this tab stop.
 * @return {HTMLElement}
 */
GrDiffBuilder.prototype._getTabWrapper = function(tabSize) {
  // Force this to be a number to prevent arbitrary injection.
  const result = this._createElement('span', 'tab');
  result.style['tab-size'] = tabSize;
  result.style['-moz-tab-size'] = tabSize;
  result.innerText = '\t';
  return result;
};

GrDiffBuilder.prototype._createElement = function(tagName, classStr) {
  const 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 (classStr) {
    for (const className of classStr.split(' ')) {
      el.classList.add(className);
    }
  }
  return el;
};

GrDiffBuilder.prototype._handleLayerUpdate = function(start, end, side) {
  this._renderContentByRange(start, end, side);
};

/**
 * Finds the next DIV.contentText element following the given element, and on
 * the same side. Will only search within a group.
 *
 * @param {HTMLElement} content
 * @param {string} side Either 'left' or 'right'
 * @return {HTMLElement}
 */
GrDiffBuilder.prototype._getNextContentOnSide = function(content, side) {
  throw Error('Subclasses must implement _getNextContentOnSide');
};

/**
 * Determines whether the given group is either totally an addition or totally
 * a removal.
 *
 * @param {!Object} group (GrDiffGroup)
 * @return {boolean}
 */
GrDiffBuilder.prototype._isTotal = function(group) {
  return group.type === GrDiffGroup.Type.DELTA &&
      (!group.adds.length || !group.removes.length) &&
      !(!group.adds.length && !group.removes.length);
};

/**
 * Set the blame information for the diff. For any already-rendered line,
 * re-render its blame cell content.
 *
 * @param {Object} blame
 */
GrDiffBuilder.prototype.setBlame = function(blame) {
  this._blameInfo = blame;

  // TODO(wyatta): make this loop asynchronous.
  for (const commit of blame) {
    for (const range of commit.ranges) {
      for (let i = range.start; i <= range.end; i++) {
        // TODO(wyatta): this query is expensive, but, when traversing a
        // range, the lines are consecutive, and given the previous blame
        // cell, the next one can be reached cheaply.
        const el = this._getBlameByLineNum(i);
        if (!el) { continue; }
        // Remove the element's children (if any).
        while (el.hasChildNodes()) {
          el.removeChild(el.lastChild);
        }
        const blame = this._getBlameForBaseLine(i, commit);
        el.appendChild(blame);
      }
    }
  }
};

/**
 * Find the blame cell for a given line number.
 *
 * @param {number} lineNum
 * @return {HTMLTableDataCellElement}
 */
GrDiffBuilder.prototype._getBlameByLineNum = function(lineNum) {
  const root = dom(this._outputEl);
  return root.querySelector(`td.blame[data-line-number="${lineNum}"]`);
};

/**
 * Given a base line number, return the commit containing that line in the
 * current set of blame information. If no blame information has been
 * provided, null is returned.
 *
 * @param {number} lineNum
 * @return {Object} The commit information.
 */
GrDiffBuilder.prototype._getBlameCommitForBaseLine = function(lineNum) {
  if (!this._blameInfo) { return null; }

  for (const blameCommit of this._blameInfo) {
    for (const range of blameCommit.ranges) {
      if (range.start <= lineNum && range.end >= lineNum) {
        return blameCommit;
      }
    }
  }
  return null;
};

/**
 * Given the number of a base line, get the content for the blame cell of that
 * line. If there is no blame information for that line, returns null.
 *
 * @param {number} lineNum
 * @param {Object=} opt_commit Optionally provide the commit object, so that
 *     it does not need to be searched.
 * @return {HTMLSpanElement}
 */
GrDiffBuilder.prototype._getBlameForBaseLine = function(lineNum, opt_commit) {
  const commit = opt_commit || this._getBlameCommitForBaseLine(lineNum);
  if (!commit) { return null; }

  const isStartOfRange = commit.ranges.some(r => r.start === lineNum);

  const date = (new Date(commit.time * 1000)).toLocaleDateString();
  const blameNode = this._createElement('span',
      isStartOfRange ? 'startOfRange' : '');

  const shaNode = this._createElement('a', 'blameDate');
  shaNode.innerText = `${date}`;
  shaNode.setAttribute('href', `/q/${commit.id}`);
  blameNode.appendChild(shaNode);

  const shortName = commit.author.split(' ')[0];
  const authorNode = this._createElement('span', 'blameAuthor');
  authorNode.innerText = ` ${shortName}`;
  blameNode.appendChild(authorNode);

  const hoverCardFragment = this._createElement('span', 'blameHoverCard');
  hoverCardFragment.innerText =
    `Commit ${commit.id}
Author: ${commit.author}
Date: ${date}

${commit.commit_msg}`;
  const hovercard = this._createElement('gr-hovercard');
  hovercard.appendChild(hoverCardFragment);
  blameNode.appendChild(hovercard);

  return blameNode;
};

/**
 * Create a blame cell for the given base line. Blame information will be
 * included in the cell if available.
 *
 * @param {GrDiffLine} line
 * @return {HTMLTableDataCellElement}
 */
GrDiffBuilder.prototype._createBlameCell = function(line) {
  const blameTd = this._createElement('td', 'blame');
  blameTd.setAttribute('data-line-number', line.beforeNumber);
  if (line.beforeNumber) {
    const content = this._getBlameForBaseLine(line.beforeNumber);
    if (content) {
      blameTd.appendChild(content);
    }
  }
  return blameTd;
};

/**
 * Finds the line number element given the content element by walking up the
 * DOM tree to the diff row and then querying for a .lineNum element on the
 * requested side.
 *
 * TODO(brohlfs): Consolidate this with getLineEl... methods in html file.
 */
GrDiffBuilder.prototype._getLineNumberEl = function(content, side) {
  let row = content;
  while (row && !row.classList.contains('diff-row')) row = row.parentElement;
  return row ? row.querySelector('.lineNum.' + side) : null;
};
