package net.hillsdon.reviki.jira.renderer;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;

import com.atlassian.jira.issue.RendererManager;
import com.atlassian.jira.issue.fields.renderer.IssueRenderContext;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.base.Optional;

import net.hillsdon.reviki.vc.SimplePageStore;
import net.hillsdon.reviki.vc.impl.DummyPageStore;
import net.hillsdon.reviki.web.urls.InterWikiLinker;
import net.hillsdon.reviki.web.urls.InternalLinker;
import net.hillsdon.reviki.web.urls.SimpleWikiUrls;
import net.hillsdon.reviki.wiki.renderer.HtmlRenderer;
import net.hillsdon.reviki.wiki.renderer.creole.SimpleAnchors;
import net.hillsdon.reviki.wiki.renderer.creole.SimpleImages;
import net.hillsdon.reviki.wiki.renderer.creole.LinkPartsHandler;
import net.hillsdon.reviki.wiki.renderer.creole.LinkResolutionContext;
import net.hillsdon.reviki.wiki.renderer.macro.Macro;

/**
 * A simple interface to Reviki's HTML rendering capabilities.
 *
 * @author msw
 */
public final class JiraRevikiRenderer {
  /** Match Confluence-style links in single square brackets. */
  private static final Pattern confluenceLinks = Pattern.compile("([^\\[]|^)(\\[[~@]*[^\\\\,\\[\\]]+?\\])([^\\]]|$)");

  /** Replacement text to turn Confluence-style links into Reviki-style links. */
  private static final String revikiReplacement = "$1[$2]$3";

  /** Render Reviki markup to HTML, complete with link handling. */
  private static final HtmlRenderer _renderer;

  /** Plugin configuration. */
  private final RevikiPluginConfiguration _pluginSettings;

  /** Reference to the renderer manager. */
  private final RendererManager _rendererManager;

  static {
    // Have all internal relative links start from /jira/browse/
    SimpleWikiUrls wikiUrls = SimpleWikiUrls.RELATIVE_TO.apply("/jira/browse/");
    InternalLinker linker = new InternalLinker(wikiUrls);

    // We know of no other wikis.
    InterWikiLinker wikilinker = new InterWikiLinker();

    // Or any pages.
    SimplePageStore pageStore = new DummyPageStore();

    // Finally, construct the renderer.
    _renderer = new HtmlRenderer(new LinkResolutionContext(linker, wikilinker, pageStore));
  }

  public JiraRevikiRenderer(final RevikiPluginConfiguration pluginSettings, final RendererManager rendererManager) {
    _pluginSettings = pluginSettings;
    _rendererManager = rendererManager;
  }

  /**
   * Render some markup to HTML.
   */
  public String render(final String text, final IssueRenderContext ctx) {
    String contents = text;

    // First fix any Confluence-style links for backwards-compatibility.
    if (_pluginSettings.convertConfluenceLinks()) {
      contents = confluenceToReviki(text);
    }

    // Try rendering it, and return the original markup if we fail.
    Optional<String> rendered = _renderer.render(contents);
    return rendered.isPresent() ? rendered.get() : text;
  }

  /**
   * Convert Confluence-style links ("[FOO-1]") to Reviki-style links
   * ("[[FOO-1]]"), this allows backwards compatibility in linking to issues.
   */
  private static String confluenceToReviki(final String text) {
    // Need to run the regex twice because of overlapping matches.
    //
    // eg: "[FOO-1] [FOO-1] [FOO-1]" - just replacing once results in
    // "[[FOO-1]] [FOO-1] [[FOO-1]]"

    String first = confluenceLinks.matcher(text).replaceAll(revikiReplacement);
    return confluenceLinks.matcher(first).replaceAll(revikiReplacement);
  }
}

@@ -508,478 +508,32 @@
 iki.
-vc.SimplePageStore;%0Aimport net.hillsdon.reviki.vc.impl.DummyPageStore;%0Aimport net.hillsdon.reviki.web.urls.InterWikiLinker;%0Aimport net.hillsdon.reviki.web.urls.InternalLinker;%0Aimport net.hillsdon.reviki.web.urls.SimpleWikiUrls;%0Aimport net.hillsdon.reviki.wiki.renderer.HtmlRenderer;%0Aimport net.hillsdon.reviki.wiki.renderer.creole.SimpleAnchors;%0Aimport net.hillsdon.reviki.wiki.renderer.creole.SimpleImages;%0Aimport net.hillsdon.reviki.wiki.renderer.creole.LinkPartsHandl
+wiki.renderer.HtmlRender
 er;%0A
@@ -606,62 +606,8 @@
 ext;
-%0Aimport net.hillsdon.reviki.wiki.renderer.macro.Macro;
 %0A%0A/*
@@ -1176,16 +1176,93 @@
 renderer
+ = new HtmlRenderer(LinkResolutionContext.SIMPLE_LINKS.apply(%22/jira/browse%22))
 ;%0A%0A  /**
@@ -1387,24 +1387,24 @@
 manager. */%0A
+
   private fi
@@ -1446,528 +1446,8 @@
 r;%0A%0A
-  static %7B%0A    // Have all internal relative links start from /jira/browse/%0A    SimpleWikiUrls wikiUrls = SimpleWikiUrls.RELATIVE_TO.apply(%22/jira/browse/%22);%0A    InternalLinker linker = new InternalLinker(wikiUrls);%0A%0A    // We know of no other wikis.%0A    InterWikiLinker wikilinker = new InterWikiLinker();%0A%0A    // Or any pages.%0A    SimplePageStore pageStore = new DummyPageStore();%0A%0A    // Finally, construct the renderer.%0A    _renderer = new HtmlRenderer(new LinkResolutionContext(linker, wikilinker, pageStore));%0A  %7D%0A%0A
   pu

Use simpler LinkResolutionContext interface