package org.ambraproject.wombat.service;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.ambraproject.wombat.service.CommentFormatting.FormattedComment;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.util.Map;
import java.util.stream.Collectors;

import static org.testng.Assert.assertEquals;

public class CommentFormattingTest {

  private static class TestCase {
    private String body;
    private String title;
    private String highlightedText;
    private String competingInterestBody;

    private String expectedBodyWithHighlightedText;
    private String expectedCompetingInterestStatement;

    public TestCase setBody(String body) {
      this.body = body;
      return this;
    }

    public TestCase setTitle(String title) {
      this.title = title;
      return this;
    }

    public TestCase setHighlightedText(String highlightedText) {
      this.highlightedText = highlightedText;
      return this;
    }

    public TestCase setCompetingInterestBody(String competingInterestBody) {
      this.competingInterestBody = competingInterestBody;
      return this;
    }

    public TestCase setExpectedBodyWithHighlightedText(String expectedBodyWithHighlightedText) {
      this.expectedBodyWithHighlightedText = expectedBodyWithHighlightedText;
      return this;
    }

    public TestCase setExpectedCompetingInterestStatement(String expectedCompetingInterestStatement) {
      this.expectedCompetingInterestStatement = expectedCompetingInterestStatement;
      return this;
    }

    public ImmutableMap<String, Object> createView() {
      ImmutableMap.Builder<String, Object> builder = ImmutableMap.<String, Object>builder();
      builder.put("replies", ImmutableList.of());
      if (body != null) builder.put("body", body);
      if (title != null) builder.put("title", title);
      if (highlightedText != null) builder.put("highlightedText", highlightedText);
      builder.put("competingInterestStatement", (competingInterestBody != null)
          ? ImmutableMap.of("body", competingInterestBody) : ImmutableMap.of());
      return builder.build();
    }
  }

  @DataProvider
  public Object[][] getTestCases() {
    return TEST_CASES.stream()
        .map(testCase -> new Object[]{testCase})
        .collect(Collectors.toList()).toArray(new Object[0][]);
  }

  @Test(dataProvider = "getTestCases")
  public void testCommentFormatting(TestCase testCase) {
    Map<String, Object> modifiedView = CommentFormatting.addFormattingFields(testCase.createView());
    FormattedComment formatted = (FormattedComment) modifiedView.get("formatting");
    assertEquals(formatted.getBodyWithHighlightedText(), testCase.expectedBodyWithHighlightedText);
    assertEquals(formatted.getCompetingInterestStatement(), testCase.expectedCompetingInterestStatement);
  }

  private static final ImmutableList<TestCase> TEST_CASES = ImmutableList.copyOf(new TestCase[]{

      // Empty case
      new TestCase()
          .setExpectedBodyWithHighlightedText("")
          .setExpectedCompetingInterestStatement(""),

      // Basic non-empty case
      new TestCase()
          .setBody("Body")
          .setTitle("Title")
          .setHighlightedText("HighlightedText")
          .setCompetingInterestBody("CompetingInterestBody")
          .setExpectedBodyWithHighlightedText("<p>HighlightedText<br/><br/>Body</p>")
          .setExpectedCompetingInterestStatement("CompetingInterestBody"),

      // Basic markup
      new TestCase()
          .setBody("Supported markup tags: ''italic'' '''bold''' '''''bold italic''''' ^^superscript^^ ~~subscript~~")
          .setExpectedBodyWithHighlightedText("<p>Supported markup tags: <em>italic</em> <strong>bold</strong> <strong><em>bold italic</em></strong> <sup>superscript</sup> <sub>subscript</sub></p>")
          .setExpectedCompetingInterestStatement(""),

      // Markup with HTML escaping
      new TestCase()
          .setBody("<p>Supported markup tags: ''<em>italic</em>'' '''<strong>bold</strong>''' '''''<strong><em>bold italic</em></strong>''''' ^^<sup>superscript</sup>^^ ~~<sub>subscript</sub>~~</p>")
          .setExpectedBodyWithHighlightedText("<p>&lt;p&gt;Supported markup tags: <em>&lt;em&gt;italic&lt;/em&gt;</em> <strong>&lt;strong&gt;bold&lt;/strong&gt;</strong> <strong><em>&lt;strong&gt;&lt;em&gt;bold italic&lt;/em&gt;&lt;/strong&gt;</em></strong> <sup>&lt;sup&gt;superscript&lt;/sup&gt;</sup> <sub>&lt;sub&gt;subscript&lt;/sub&gt;</sub>&lt;/p&gt;</p>")
          .setExpectedCompetingInterestStatement(""),

      // URL detection
      new TestCase()
          .setBody("Visit example.com")
          .setExpectedBodyWithHighlightedText("<p>Visit example.com</p>")
          .setExpectedCompetingInterestStatement(""),
      new TestCase()
          .setBody("Visit www.example.com")
          .setExpectedBodyWithHighlightedText("<p>Visit <a href=\"http://www.example.com\">www.example.com</a></p>")
          .setExpectedCompetingInterestStatement(""),
      new TestCase()
          .setBody("Visit http://example.com")
          .setExpectedBodyWithHighlightedText("<p>Visit <a href=\"http://example.com\">http://example.com</a></p>")
          .setExpectedCompetingInterestStatement(""),
      new TestCase()
          .setBody("Visit http://www.example.com")
          .setExpectedBodyWithHighlightedText("<p>Visit <a href=\"http://www.example.com\">http://www.example.com</a></p>")
          .setExpectedCompetingInterestStatement(""),

  });

}

@@ -286,16 +286,42 @@
 .Test;%0A%0A
+import java.util.HashMap;%0A
 import j
@@ -1638,148 +1638,171 @@
     
-public ImmutableMap%3CString, Object%3E createView() %7B%0A      ImmutableMap.Builder%3CString, Object%3E builder = ImmutableMap.%3CString, Object%3Ebuilder
+/**%0A     * Represent this test case as a mutable metadata map.%0A     */%0A    public Map%3CString, Object%3E createView() %7B%0A      Map%3CString, Object%3E view = new HashMap%3C%3E
 ();%0A
@@ -1803,31 +1803,28 @@
 %3C%3E();%0A      
-builder
+view
 .put(%22replie
@@ -1868,31 +1868,28 @@
 dy != null) 
-builder
+view
 .put(%22body%22,
@@ -1917,31 +1917,28 @@
 le != null) 
-builder
+view
 .put(%22title%22
@@ -1982,23 +1982,20 @@
 = null) 
-builder
+view
 .put(%22hi
@@ -2034,23 +2034,20 @@
 ;%0A      
-builder
+view
 .put(%22co
@@ -2203,23 +2203,12 @@
 urn 
-builder.build()
+view
 ;%0A  
@@ -2542,22 +2542,41 @@
 ct%3E 
-modifiedView =
+view = testCase.createView();%0A   
  Com
@@ -2610,37 +2610,20 @@
 gFields(
-testCase.createV
+v
 iew
-()
 );%0A    F
@@ -2673,17 +2673,9 @@
 nt) 
-modifiedV
+v
 iew.

Fix unit test