/**
 * @license
 * 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.
 */

import 'ba-linkify/ba-linkify';
import {getBaseUrl} from '../../../utils/url-util';
import {CommentLinkInfo} from '../../../types/common';

/**
 * Pattern describing URLs with supported protocols.
 */
const URL_PROTOCOL_PATTERN = /^(.*)(https?:\/\/|mailto:)/;

export type LinkTextParserCallback = ((text: string, href: string) => void) &
  ((text: null, href: null, fragment: DocumentFragment) => void);

export interface CommentLinkItem {
  position: number;
  length: number;
  html: HTMLAnchorElement | DocumentFragment;
}

export type LinkTextParserConfig = {[name: string]: CommentLinkInfo};

export class GrLinkTextParser {
  private readonly baseUrl = getBaseUrl();

  /**
   * Construct a parser for linkifying text. Will linkify plain URLs that appear
   * in the text as well as custom links if any are specified in the linkConfig
   * parameter.
   *
   * @constructor
   * @param linkConfig Comment links as specified by the commentlinks field on a
   *     project config.
   * @param callback The callback to be fired when an intermediate parse result
   *     is emitted. The callback is passed text and href strings if a link is to
   *     be created, or a document fragment otherwise.
   * @param removeZeroWidthSpace If true, zero-width spaces will be removed from
   *     R=<email> and CC=<email> expressions.
   */
  constructor(
    private readonly linkConfig: LinkTextParserConfig,
    private readonly callback: LinkTextParserCallback,
    private readonly removeZeroWidthSpace?: boolean
  ) {
    Object.preventExtensions(this);
  }

  /**
   * Emit a callback to create a link element.
   *
   * @param text The text of the link.
   * @param href The URL to use as the href of the link.
   */
  addText(text: string, href: string) {
    if (!text) {
      return;
    }
    this.callback(text, href);
  }

  /**
   * Given the source text and a list of CommentLinkItem objects that were
   * generated by the commentlinks config, emit parsing callbacks.
   *
   * @param text The chuml of source text over which the outputArray items range.
   * @param outputArray The list of items to add resulting from commentlink
   *     matches.
   */
  processLinks(text: string, outputArray: CommentLinkItem[]) {
    this.sortArrayReverse(outputArray);
    const fragment = document.createDocumentFragment();
    let 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(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);
  }

  /**
   * Sort the given array of CommentLinkItems such that the positions are in
   * reverse order.
   */
  sortArrayReverse(outputArray: CommentLinkItem[]) {
    outputArray.sort((a, b) => b.position - a.position);
  }

  addItem(
    text: string,
    href: string,
    html: null,
    position: number,
    length: number,
    outputArray: CommentLinkItem[]
  ): void;

  addItem(
    text: null,
    href: null,
    html: string,
    position: number,
    length: number,
    outputArray: CommentLinkItem[]
  ): void;

  /**
   * Create a CommentLinkItem and append it to the given output array. This
   * method can be called in either of two ways:
   * - With `text` and `href` parameters provided, and the `html` parameter
   *   passed as `null`. In this case, the new CommentLinkItem will be a link
   *   element with the given text and href value.
   * - With the `html` paremeter provided, and the `text` and `href` parameters
   *   passed as `null`. In this case, the string of HTML will be parsed and the
   *   first resulting node will be used as the resulting content.
   *
   * @param text The text to use if creating a link.
   * @param href The href to use as the URL if creating a link.
   * @param html The html to parse and use as the result.
   * @param  position The position inside the source text where the item
   *     starts.
   * @param length The number of characters in the source text
   *     represented by the item.
   * @param outputArray The array to which the
   *     new item is to be appended.
   */
  addItem(
    text: string | null,
    href: string | null,
    html: string | null,
    position: number,
    length: number,
    outputArray: CommentLinkItem[]
  ): void {
    if (href) {
      const a = document.createElement('a');
      a.setAttribute('href', href);
      a.textContent = text;
      a.target = '_blank';
      a.rel = 'noopener';
      outputArray.push({
        html: a,
        position,
        length,
      });
    } else if (html) {
      // addItem has 2 overloads. If href is null, then html
      // can't be null.
      // TODO(TS): remove if(html) and keep else block without condition
      const fragment = document.createDocumentFragment();
      // Create temporary div to hold the nodes in.
      const div = document.createElement('div');
      div.innerHTML = html;
      while (div.firstChild) {
        fragment.appendChild(div.firstChild);
      }
      outputArray.push({
        html: fragment,
        position,
        length,
      });
    }
  }

  /**
   * Create a CommentLinkItem for a link and append it to the given output
   * array.
   *
   * @param text The text for the link.
   * @param href The href to use as the URL of the link.
   * @param position The position inside the source text where the link
   *     starts.
   * @param length The number of characters in the source text
   *     represented by the link.
   * @param outputArray The array to which the
   *     new item is to be appended.
   */
  addLink(
    text: string,
    href: string,
    position: number,
    length: number,
    outputArray: CommentLinkItem[]
  ) {
    // TODO(TS): remove !test condition
    if (!text || this.hasOverlap(position, length, outputArray)) {
      return;
    }
    if (
      !!this.baseUrl &&
      href.startsWith('/') &&
      !href.startsWith(this.baseUrl)
    ) {
      href = this.baseUrl + href;
    }
    this.addItem(text, href, null, position, length, outputArray);
  }

  /**
   * Create a CommentLinkItem specified by an HTMl string and append it to the
   * given output array.
   *
   * @param html The html to parse and use as the result.
   * @param position The position inside the source text where the item
   *     starts.
   * @param length The number of characters in the source text
   *     represented by the item.
   * @param outputArray The array to which the
   *     new item is to be appended.
   */
  addHTML(
    html: string,
    position: number,
    length: number,
    outputArray: CommentLinkItem[]
  ) {
    if (this.hasOverlap(position, length, outputArray)) {
      return;
    }
    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);
  }

  /**
   * Does the given range overlap with anything already in the item list.
   */
  hasOverlap(position: number, length: number, outputArray: CommentLinkItem[]) {
    const endPosition = position + length;
    for (let i = 0; i < outputArray.length; i++) {
      const arrayItemStart = outputArray[i].position;
      const arrayItemEnd = outputArray[i].position + outputArray[i].length;
      if (
        (position >= arrayItemStart && position < arrayItemEnd) ||
        (endPosition > arrayItemStart && endPosition <= arrayItemEnd) ||
        (position === arrayItemStart && position === arrayItemEnd)
      ) {
        return true;
      }
    }
    return false;
  }

  /**
   * Parse the given source text and emit callbacks for the items that are
   * parsed.
   */
  parse(text?: string | null) {
    if (text) {
      window.linkify(text, {
        callback: this.parseChunk.bind(this),
      });
    }
  }

  /**
   * Callback that is pased into the linkify function. ba-linkify will call this
   * method in either of two ways:
   * - With both a `text` and `href` parameter provided: this indicates that
   *   ba-linkify has found a plain URL and wants it linkified.
   * - With only a `text` parameter provided: this represents the non-link
   *   content that lies between the links the library has found.
   *
   */
  parseChunk(text: string, href?: string) {
    // 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 the href is provided then ba-linkify has recognized it as a URL. If
    // the source text does not include a protocol, the protocol will be added
    // by ba-linkify. Create the link if the href is provided and its protocol
    // matches the expected pattern.
    if (href) {
      const result = URL_PROTOCOL_PATTERN.exec(href);
      if (result) {
        const prefixText = result[1];
        if (prefixText.length > 0) {
          // Fix for simple cases from
          // https://bugs.chromium.org/p/gerrit/issues/detail?id=11697
          // When leading whitespace is missed before link,
          // linkify add this text before link as a schema name to href.
          // We suppose, that prefixText just a single word
          // before link and add this word as is, without processing
          // any patterns in it.
          this.parseLinks(prefixText, {});
          text = text.substring(prefixText.length);
          href = href.substring(prefixText.length);
        }
        this.addText(text, href);
        return;
      }
    }
    // For the sections of text that lie between the links found by
    // ba-linkify, we search for the project-config-specified link patterns.
    this.parseLinks(text, this.linkConfig);
  }

  /**
   * Walk over the given source text to find matches for comemntlink patterns
   * and emit parse result callbacks.
   *
   * @param text The raw source text.
   * @param config A comment links specification object.
   */
  parseLinks(text: string, config: LinkTextParserConfig) {
    // The outputArray is used to store all of the matches found for all
    // patterns.
    const outputArray: CommentLinkItem[] = [];
    for (const p in config) {
      // TODO(TS): it seems, the following line can be rewritten as:
      // if(enabled === false || enabled === 0 || enabled === '')
      // Should be double-checked before update
      // eslint-disable-next-line eqeqeq
      if (config[p].enabled != null && config[p].enabled == false) {
        continue;
      }
      // PolyGerrit doesn't use hash-based navigation like the GWT UI.
      // Account for this.
      const html = config[p].html;
      const link = config[p].link;
      if (html) {
        config[p].html = html.replace(/<a href="#\//g, '<a href="/');
      } else if (link) {
        if (link[0] === '#') {
          config[p].link = link.substr(1);
        }
      }

      const pattern = new RegExp(config[p].match, 'g');

      let match;
      let textToCheck = text;
      let susbtrIndex = 0;

      while ((match = pattern.exec(textToCheck))) {
        textToCheck = textToCheck.substr(match.index + match[0].length);
        let result = match[0].replace(
          pattern,
          // Either html or link has a value. Otherwise an exception is thrown
          // in the code below.
          (config[p].html || config[p].link)!
        );

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

          this.addHTML(
            result,
            susbtrIndex + match.index + i,
            match[0].length - i,
            outputArray
          );
        } else if (config[p].link) {
          this.addLink(
            match[0],
            result,
            susbtrIndex + match.index,
            match[0].length,
            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);
  }
}
