// Copyright (C) 2015 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.

'use strict';

function GrLinkTextParser(linkConfig, callback, opt_removeZeroWidthSpace) {
  this.linkConfig = linkConfig;
  this.callback = callback;
  this.removeZeroWidthSpace = opt_removeZeroWidthSpace;
  Object.preventExtensions(this);
}

GrLinkTextParser.prototype.addText = function(text, href) {
  if (!text) {
    return;
  }
  this.callback(text, href);
};

GrLinkTextParser.prototype.processLinks = function(text, outputArray) {
  this.sortArrayReverse(outputArray);
  var fragment = document.createDocumentFragment();
  var cursor = text.length;

  // Start inserting linkified URLs from the end of the String. That way, the
  // string positions of the items don't change as we iterate through.
  outputArray.forEach(function(item) {
    // Add any text between the current linkified item and the item added before
    // if it exists.
    if (item.position + item.length !== cursor) {
      fragment.insertBefore(
          document.createTextNode(
              text.slice(item.position + item.length, cursor)),
          fragment.firstChild);
    }
    fragment.insertBefore(item.html, fragment.firstChild);
    cursor = item.position;
  });

  // Add the beginning portion at the end.
  if (cursor !== 0) {
    fragment.insertBefore(
        document.createTextNode(text.slice(0, cursor)), fragment.firstChild);
  }

  this.callback(null, null, fragment);
};

GrLinkTextParser.prototype.sortArrayReverse = function(outputArray) {
  outputArray.sort(function(a, b) {return b.position - a.position});
};

GrLinkTextParser.prototype.addItem =
    function(text, href, html, position, length, outputArray) {
  var htmlOutput = '';

  if (href) {
    var a = document.createElement('a');
    a.href = href;
    a.textContent = text;
    a.target = '_blank';
    a.rel = 'noopener';
    htmlOutput = a;
  } else if (html) {
    var fragment = document.createDocumentFragment();
    // Create temporary div to hold the nodes in.
    var div = document.createElement('div');
    div.innerHTML = html;
    while (div.firstChild) {
      fragment.appendChild(div.firstChild);
    }
    htmlOutput = fragment;
  }

  outputArray.push({
    html: htmlOutput,
    position: position,
    length: length,
  });
};

GrLinkTextParser.prototype.addLink =
    function(text, href, position, length, outputArray) {
  if (!text) {
    return;
  }
  if (!this.hasOverlap(position, length, outputArray)) {
    this.addItem(text, href, null, position, length, outputArray);
  }
};

GrLinkTextParser.prototype.addHTML =
    function(html, position, length, outputArray) {
  if (!this.hasOverlap(position, length, outputArray)) {
    this.addItem(null, null, html, position, length, outputArray);
  }
};

GrLinkTextParser.prototype.hasOverlap =
    function(position, length, outputArray) {
  var endPosition = position + length;
  for (var i = 0; i < outputArray.length; i++) {
    var arrayItemStart = outputArray[i].position;
    var arrayItemEnd = outputArray[i].position + outputArray[i].length;
    if ((position >= arrayItemStart && position < arrayItemEnd) ||
      (endPosition > arrayItemStart && endPosition <= arrayItemEnd) ||
      (position === arrayItemStart && position === arrayItemEnd)) {
          return true;
    }
  }
  return false;
};

GrLinkTextParser.prototype.parse = function(text) {
  linkify(text, {
    callback: this.parseChunk.bind(this),
  });
};

GrLinkTextParser.prototype.parseChunk = function(text, href) {
  // TODO(wyatta) switch linkify sequence, see issue 5526.
  if (this.removeZeroWidthSpace) {
    // Remove the zero-width space added in gr-change-view.
    text = text.replace(/^(CC|R)=\u200B/gm, '$1=');
  }

  if (href) {
    this.addText(text, href);
  } else {
    this.parseLinks(text, this.linkConfig);
  }
};

GrLinkTextParser.prototype.parseLinks = function(text, patterns) {
  // The outputArray is used to store all of the matches found for all patterns.
  var outputArray = [];
  for (var p in patterns) {
    if (patterns[p].enabled != null && patterns[p].enabled == false) {
      continue;
    }
    // PolyGerrit doesn't use hash-based navigation like GWT.
    // Account for this.
    // TODO(andybons): Support Gerrit being served from a base other than /,
    // e.g. https://git.eclipse.org/r/
    if (patterns[p].html) {
      patterns[p].html =
          patterns[p].html.replace(/<a href=\"#\//g, '<a href="/');
    } else if (patterns[p].link) {
      if (patterns[p].link[0] == '#') {
        patterns[p].link = patterns[p].link.substr(1);
      }
    }

    var pattern = new RegExp(patterns[p].match, 'g');

    var match;
    var textToCheck = text;
    var susbtrIndex = 0;

    while ((match = pattern.exec(textToCheck)) != null) {
      textToCheck = textToCheck.substr(match.index + match[0].length);
      var result = match[0].replace(pattern,
          patterns[p].html || patterns[p].link);

      // Skip portion of replacement string that is equal to original.
      for (var i = 0; i < result.length; i++) {
        if (result[i] !== match[0][i]) {
          break;
        }
      }
      result = result.slice(i);

      if (patterns[p].html) {
        this.addHTML(
          result,
          susbtrIndex + match.index + i,
          match[0].length - i,
          outputArray);
      } else if (patterns[p].link) {
        this.addLink(
          match[0],
          result,
          susbtrIndex + match.index + i,
          match[0].length - i,
          outputArray);
      } else {
        throw Error('linkconfig entry ' + p +
            ' doesn’t contain a link or html attribute.');
      }

      // Update the substring location so we know where we are in relation to
      // the initial full text string.
      susbtrIndex = susbtrIndex + match.index + match[0].length;
    }
  }
  this.processLinks(text, outputArray);
};
