package org.codiki.core.services;

import org.apache.commons.lang.StringEscapeUtils;
import org.junit.Before;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class ParserServiceTest {

    private ParserService parserService;

    @Before
    public void setUp() {
        parserService = new ParserService();
    }

    /* *********************************************************** */
    /* H E A D E R S   P A R S I N G */
    /* *********************************************************** */

    @Test
    public void testParseHeaders_h1() {
        final String strInit = "[h1]Header[/h1]";
        final String strExpected = "<h1>Header</h1>";

        assertThat(parserService.parseHeaders(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseHeaders_h2() {
        final String strInit = "[h2]Header[/h2]";
        final String strExpected = "<h2>Header</h2>";

        assertThat(parserService.parseHeaders(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseHeaders_h3() {
        final String strInit = "[h3]Header[/h3]";
        final String strExpected = "<h3>Header</h3>";

        assertThat(parserService.parseHeaders(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseHeader_onlyCoupleOfTags() {
        final String strInit = "[h1][h1]Test[/h1]";
        final String strExpected = "[h1]<h1>Test</h1>";

        assertThat(parserService.parseHeaders(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseHeader_multipleCouples() {
        final String strInit = "[h1]Test1[/h1] [h1]Test2[/h1]";
        final String strExpected = "<h1>Test1</h1> <h1>Test2</h1>";

        assertThat(parserService.parseHeaders(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseHeaders() {
        final String strInit = "[h1]Header1[/h1]\n" +
                "                    Some text in header1\n" +
                "                    [h2]Header2[/h2]\n" +
                "                    Some text in header2\n" +
                "                    [h3]Header3[/h3]\n" +
                "                    Some text in header3\n" +
                "                    [h3][h3]Header3[/h3]\n" +
                "                    Some text in header3\n" +
                "                    [h2]Header2[/h2]\n" +
                "                    Some text in header2\n" +
                "                    [h3]Header3[/h3][/h3]\n" +
                "                    Some text in header3\n" +
                "                    [h1]Header1[/h1]\n" +
                "                    Some text in header1";

        final String strExpected = "<h1>Header1</h1>\n" +
                "                    Some text in header1\n" +
                "                    <h2>Header2</h2>\n" +
                "                    Some text in header2\n" +
                "                    <h3>Header3</h3>\n" +
                "                    Some text in header3\n" +
                "                    [h3]<h3>Header3</h3>\n" +
                "                    Some text in header3\n" +
                "                    <h2>Header2</h2>\n" +
                "                    Some text in header2\n" +
                "                    <h3>Header3[/h3]</h3>\n" +
                "                    Some text in header3\n" +
                "                    <h1>Header1</h1>\n" +
                "                    Some text in header1";

        assertThat(parserService.parseHeaders(strInit)).isEqualTo(strExpected);
    }

    /* *********************************************************** */
    /* B A C K   S P A C E S   P A R S I N G */
    /* *********************************************************** */

    @Test
    public void testParseBackSpaces() {
        final String strInit = "Hello\nworld!";
        final String strExpected = "Hello<br/>world!";

        assertThat(parserService.parseBackSpaces(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseBackSpaces_endTagCode() {
        final String strInit = "[/code]\n\n";
        final String strExpected = "[/code]\n";

        assertThat(parserService.parseBackSpaces(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseBackSpaces_endTagCode_2() {
        final String strInit = "[/code]\n";
        final String strExpected = "[/code]<br/>";

        assertThat(parserService.parseBackSpaces(strInit)).isEqualTo(strExpected);
    }

    /* *********************************************************** */
    /* I M A G E S   P A R S I N G */
    /* *********************************************************** */

    @Test
    public void testParseImages_simpleImg() {
        final String strInit = StringEscapeUtils.escapeHtml("[img src=\"pathToImage\" /]");
        final String strExpected = "<img src=\"pathToImage\" alt=\"\" />";

        assertThat(parserService.parseImages(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseImages_subTagAlt() {
        final String strInit = StringEscapeUtils.escapeHtml("[img src=\"pathToImage\" alt=\"alternative\" /]");
        final String strExpected = "<img src=\"pathToImage\" alt=\"alternative\" />";

        assertThat(parserService.parseImages(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseImages_multipleImages() {
        final String strInit = StringEscapeUtils.escapeHtml("[img src=\"pathToImage1\" /]\n" +
                "                    [img src=\"pathToImage2\" /]");
        final String strExpected = "<img src=\"pathToImage1\" alt=\"\" />\n" +
                "                    <img src=\"pathToImage2\" alt=\"\" />";

        assertThat(parserService.parseImages(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseImages() {
        final String strInit = StringEscapeUtils.escapeHtml("[img src=\"pathToImage1\" /]\n" +
                "                    [img src=\"pathToImage2\" alt=\"alternativeOfImage2\" /]\n" +
                "                    [img src=\"pathToImage3\" lgd=\"legendOfImage3\" /]\n" +
                "                    [img src=\"pathToImage4\" alt=\"alternativeOfImage4\" lgd=\"legendOfImage4\" /]\n" +
                "                    [img src=\"pathToImage5\" \" /]\n" +
                "                    [img src=\"pathToImage6\" src=\"pathToImage6_2\" /]\n" +
                "                    [img src=\"pathToImage7\" alt=\"alternativeOfImage7\" alt=\"alternativeOfImage7_2\" /]\n" +
                "                    [img src=\"pathToImage8\" alt=\"legendOfImage8\" alt=\"legendOfImage8_2\" /]\n" +
                "                    [img alt=\"alternativeOfImage9\" src=\"pathToImage9\" lgd=\"legendOfImage9\" /]\n" +
                "                    [img lgd=\"legendOfImage10\" src=\"pathToImage10\" alt=\"alternativeOfImage10\" /]\n" +
                "                    [img lgd=\"legendOfImage11\" alt=\"alternativeOfImage11\" src=\"pathToImage11\" /]");

        final String strExpected = "<img src=\"pathToImage1\" alt=\"\" />\n" +
                "                    <img src=\"pathToImage2\" alt=\"alternativeOfImage2\" />\n" +
                "                    [img src=&quot;pathToImage3&quot; lgd=&quot;legendOfImage3&quot; /]\n" +
                "                    [img src=&quot;pathToImage4&quot; alt=&quot;alternativeOfImage4&quot; lgd=&quot;legendOfImage4&quot; /]\n" +
                "                    [img src=&quot;pathToImage5&quot; &quot; /]\n" +
                "                    [img src=&quot;pathToImage6&quot; src=&quot;pathToImage6_2&quot; /]\n" +
                "                    [img src=&quot;pathToImage7&quot; alt=&quot;alternativeOfImage7&quot; alt=&quot;alternativeOfImage7_2&quot; /]\n" +
                "                    [img src=&quot;pathToImage8&quot; alt=&quot;legendOfImage8&quot; alt=&quot;legendOfImage8_2&quot; /]\n" +
                "                    [img alt=&quot;alternativeOfImage9&quot; src=&quot;pathToImage9&quot; lgd=&quot;legendOfImage9&quot; /]\n" +
                "                    [img lgd=&quot;legendOfImage10&quot; src=&quot;pathToImage10&quot; alt=&quot;alternativeOfImage10&quot; /]\n" +
                "                    [img lgd=&quot;legendOfImage11&quot; alt=&quot;alternativeOfImage11&quot; src=&quot;pathToImage11&quot; /]";

        assertThat(parserService.parseImages(strInit)).isEqualTo(strExpected);
    }

    /* *********************************************************** */
    /* L I N K S   P A R S I N G */
    /* *********************************************************** */

    @Test
    public void testParseLinks_simpleLink() {
        final String strInit = StringEscapeUtils.escapeHtml("[link href=\"pathToLink\" txt=\"textOfLink\" /]");
        final String strExpected = "<a href=\"pathToLink\">textOfLink</a>";

        assertThat(parserService.parseLinks(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseLinks_multipleLinks() {
        final String strInit = StringEscapeUtils.escapeHtml("[link href=\"pathToLink1\" txt=\"textOfLink1\" /]\n" +
                "                    [link href=\"pathToLink2\" txt=\"textOfLink2\" /]");
        final String strExpected = "<a href=\"pathToLink1\">textOfLink1</a>\n" +
                "                    <a href=\"pathToLink2\">textOfLink2</a>";

        assertThat(parserService.parseLinks(strInit)).isEqualTo(strExpected);
    }

    /* *********************************************************** */
    /* C O D E   P A R S I N G */
    /* *********************************************************** */

    @Test
    public void testParseCode_simpleCode() {
        final String strInit = parserService.parseBackSpaces(StringEscapeUtils.escapeHtml("[code lg=\"python\"]\n" +
                "def foo():\n" +
                "    return \"Hello world!\"\n" +
                "[/code]\n" +
                "\n"));
        final String strExpected = "<pre class=\"line-numbers\"><code class=\"language-python\">def foo():\n    return &quot;Hello world!&quot;\n</code></pre>";

        assertThat(parserService.parseCode(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseCode_multipleCodes() {
        final String strInit = parserService.parseBackSpaces(StringEscapeUtils.escapeHtml("[code lg=\"python\"]\n" +
                "def foo():\n" +
                "    return \"Hello world!\"\n" +
                "[/code]\n" +
                "\n" +
                "[code lg=\"java\"]\n" +
                "public static void main(final String... pArgs) {\n" +
                "    System.out.println(\"Hello world!\");\n" +
                "}\n" +
                "[/code]\n" +
                "\n"));
        final String strExpected = "<pre class=\"line-numbers\"><code class=\"language-python\">def foo():\n    return &quot;Hello world!&quot;\n</code></pre><pre class=\"line-numbers\"><code class=\"language-java\">public static void main(final String... pArgs) {\n    System.out.println(&quot;Hello world!&quot;);\n}\n</code></pre>";

        assertThat(parserService.parseCode(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseLinks_backSlashAndCodeParsing() {
        final String strInit = parserService.parseBackSpaces(StringEscapeUtils.escapeHtml("[code lg=\"python\"]\n" +
                "def foo():\n" +
                "    return \"Hello world!\"\n" +
                "[/code]\n" +
                "\n"));
        final String strExpected = "<pre class=\"line-numbers\"><code class=\"language-python\">def foo():\n    return &quot;Hello world!&quot;\n</code></pre>";

        assertThat(parserService.parseCode(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParseLinks_backSlashAndCodeParsing_multiple() {
        final String strInit = parserService.parseBackSpaces(StringEscapeUtils.escapeHtml("[code lg=\"python\"]\n" +
                "def foo():\n" +
                "    return \"Hello world!\"\n" +
                "[/code]\n" +
                "\n" +
                "[code lg=\"java\"]\n" +
                "public static void main(final String... pArgs) {\n" +
                "    System.out.println(\"Hello world!\");\n" +
                "}\n" +
                "[/code]\n" +
                "\n"));
        final String strExpected = "<pre class=\"line-numbers\"><code class=\"language-python\">def foo():\n    return &quot;Hello world!&quot;\n</code></pre><pre class=\"line-numbers\"><code class=\"language-java\">public static void main(final String... pArgs) {\n    System.out.println(&quot;Hello world!&quot;);\n}\n</code></pre>";

        assertThat(parserService.parseCode(strInit)).isEqualTo(strExpected);
    }

    @Test
    public void testParse() {
        final String strInit = "\n" +
                "[h1]Title 1[/h1]\n" +
                "[h2]Title 2[/h2]\n" +
                "[h3]Title 3[/h3]\n" +
                "Some text on multiple\n" +
                "lines\n" +
                "like\n" +
                "here!\n" +
                "\n" +
                "[img src=\"pathToImage\" alt=\"alternativeOfImage\" /]\n" +
                "\n" +
                "[code lg=\"java\"]\n" +
                "public static void main(final String... pArgs) {\n" +
                "    System.out.println(\"Hello world!\");\n" +
                "}\n" +
                "[/code]\n" +
                "\n" +
                "\n" +
                "[link href=\"pathToLink1\" txt=\"textOfLink1\" /]\n" +
                "\n" +
                "[img src=\"pathToImage2\" alt=\"alternativeOfImage2\" lgd=\"legendOfImage2\" /]\n" +
                "[link href=\"pathToLink2\" txt=\"textOfLink2\" /]\n" +
                "\n" +
                "[code lg=\"python\"]\n" +
                "def foo():\n" +
                "    return \"Hello world!\"\n" +
                "[/code]\n" +
                "\n" +
                "";

        final String strExpected = "<br/>" +
                "<h1>Title 1</h1><br/>" +
                "<h2>Title 2</h2><br/>" +
                "<h3>Title 3</h3><br/>" +
                "Some text on multiple<br/>" +
                "lines<br/>" +
                "like<br/>" +
                "here!<br/>" +
                "<br/>" +
                "<img src=\"pathToImage\" alt=\"alternativeOfImage\" /><br/>" +
                "<br/>" +
                "<pre class=\"line-numbers\"><code class=\"language-java\">" +
                "public static void main(final String... pArgs) {\n" +
                "    System.out.println(&quot;Hello world!&quot;);\n" +
                "}\n" +
                "</code></pre><br/>" +
                "<a href=\"pathToLink1\">textOfLink1</a><br/>" +
                "<br/>" +
                "[img src=&quot;pathToImage2&quot; alt=&quot;alternativeOfImage2&quot; lgd=&quot;legendOfImage2&quot; /]<br/>" +
                "<a href=\"pathToLink2\">textOfLink2</a><br/>" +
                "<br/>" +
                "<pre class=\"line-numbers\"><code class=\"language-python\">" +
                "def foo():\n" +
                "    return &quot;Hello world!&quot;\n" +
                "</code></pre>";

        assertThat(parserService.parse(strInit)).isEqualTo(strExpected);
    }
}
