// 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) {
  this.linkConfig = linkConfig;
  this.callback = callback;
  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';
    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) {
  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);
};
