/**
 * @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 {getBaseUrl} from '../../../utils/url-util.js';
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.');
  }

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

GrDiffBuilder.prototype.clear = function() {
  for (const layer of this.layers) {
    if (layer.removeListener) {
      layer.removeListener(this._layerUpdateListener);
    }
  }
};

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) {
    // Both td and button need a number of classes/attributes for various
    // selectors to work.
    this._decorateLineEl(td, number, side);
    td.classList.add('lineNum');

    if (this._prefs.show_file_comment_button === false && number === 'FILE') {
      return td;
    }

    const button = this._createElement('button');
    td.appendChild(button);
    button.tabIndex = -1;
    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', `${getBaseUrl()}/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;
};
