// 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;
  this.baseUrl = Gerrit.BaseUrlBehavior.getBaseUrl();
  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)) {
    if (!!this.baseUrl && href.startsWith('/') &&
          !href.startsWith(this.baseUrl)) {
      href = this.baseUrl + href;
    }
    this.addItem(text, href, null, position, length, outputArray);
  }
};

GrLinkTextParser.prototype.addHTML =
    function(html, position, length, outputArray) {
  if (!this.hasOverlap(position, length, outputArray)) {
    if (!!this.baseUrl && html.match(/<a href=\"\//g) &&
         !new RegExp(`<a href="${this.baseUrl}`, 'g').test(html)) {
      html = html.replace(/<a href=\"\//g, `<a href=\"${this.baseUrl}\/`);
    }
    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);
};
