/*
 *  @author Ranides Atterwim <ranides@gmail.com>
 *  @copyright Ranides Atterwim
 *  @license WTFPL
 *  @url http://ranides.net/projects/assira
 */

package net.ranides.assira.text;

import org.apache.commons.lang3.text.StrBuilder;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author ranides
 */
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
public class StringCompilerTest {
    
    public static String apacheQuote(String value) {
        if (null == value) {
            return "\"\"";
        }
        return "\"" + new StrBuilder(value).replaceAll("\\", "\\\\").replaceAll("\"", "\\\"") + "\"";
    }
    
    public static String apacheUnquote(String value) {
        final String test = StringCompiler.unquoteCheck(value);
        if(null != test) { return test; }

        return new StrBuilder(value.substring(1, value.length()-1) )
            .replaceAll("\\\\", "\\")
            .replaceAll("\\\"", "\"")
            .toString();
    }

    @Test
    public void testQuote() {
        assertEquals( "\"abc\"", StringCompiler.quote("abc") );
        assertEquals( "\"a\\\"bc\"", StringCompiler.quote("a\"bc") );
        assertEquals( "\"a\\\"bc c:\\\\v\"", StringCompiler.quote("a\"bc c:\\v") );
        assertEquals( "\"a\\\"bc c:\\\\vdata\b \"", StringCompiler.quote("a\"bc c:\\vdata\b ") );
        assertEquals( "\"a\\\"bc c:\\\\vdata\\\\\b \"", StringCompiler.quote("a\"bc c:\\vdata\\\b ") );
    }

    @Test
    public void testUnquote() {
        assertEquals("", StringCompiler.unquote("") );
        assertEquals("a", StringCompiler.unquote("a") );
        assertEquals("abc", StringCompiler.unquote("abc") );
        
        assertEquals("",                StringCompiler.unquote("\"\"") );
        assertEquals("a",               StringCompiler.unquote("\"a\"") );
        assertEquals("abc",             StringCompiler.unquote("\"abc\"") );
        assertEquals("abc \\hello",     StringCompiler.unquote("\"abc \\hello\"") );
        assertEquals("abc \\hello",     StringCompiler.unquote("\"abc \\\\hello\"") );
        assertEquals("abc \"hello",     StringCompiler.unquote("\"abc \\\\\"hello\"") );
        assertEquals("abc \\ \"hello",  StringCompiler.unquote("\"abc \\\\ \"hello\"") );
        assertEquals("abc \\ \"hello",  StringCompiler.unquote("\"abc \\\\ \\\"hello\"") );
        assertEquals("abc \\\"hello",   StringCompiler.unquote("\"abc \\\\\\\"hello\"") );
        
        // invalid, ale niech będzie test takiej sytuacji. nie-escape'owane " po prostu zostawiamy
        assertEquals("abc \\\"\"hello",   StringCompiler.unquote("\"abc \\\\\\\"\"hello\"") );
        assertEquals("abc \\\"\"he\"llo",   StringCompiler.unquote("\"abc \\\\\\\"\"he\"llo\"") );
        
        try {
            StringCompiler.unquote("\"");
            fail("IllegalArgumentException expected");
        } catch(IllegalArgumentException _e) {
            assertTrue(true);
        }
        
        try {
            StringCompiler.unquote("abc\"");
            fail("IllegalArgumentException expected");
        } catch(IllegalArgumentException _e) {
            assertTrue(true);
        }
        
        try {
            StringCompiler.unquote("\"abc");
            fail("IllegalArgumentException expected");
        } catch(IllegalArgumentException _e) {
            assertTrue(true);
        }
    }
    
    @Test
    public void testUnquoteApache() {
        assertEquals("", apacheUnquote("") );
        assertEquals("a", apacheUnquote("a") );
        assertEquals("abc", apacheUnquote("abc") );
        
        assertEquals("",                apacheUnquote("\"\"") );
        assertEquals("a",               apacheUnquote("\"a\"") );
        assertEquals("abc",             apacheUnquote("\"abc\"") );
        assertEquals("abc \\hello",     apacheUnquote("\"abc \\hello\"") );
        assertEquals("abc \\hello",     apacheUnquote("\"abc \\\\hello\"") );
        assertEquals("abc \"hello",     apacheUnquote("\"abc \\\\\"hello\"") );
        assertEquals("abc \\ \"hello",  apacheUnquote("\"abc \\\\ \"hello\"") );
        assertEquals("abc \\ \"hello",  apacheUnquote("\"abc \\\\ \\\"hello\"") );
        assertEquals("abc \\\"hello",   apacheUnquote("\"abc \\\\\\\"hello\"") );
        
        // invalid, ale niech będzie test. nie-escape'owane " po prostu zostawiamy
        assertEquals("abc \\\"\"hello",   apacheUnquote("\"abc \\\\\\\"\"hello\"") );
        assertEquals("abc \\\"\"he\"llo",   apacheUnquote("\"abc \\\\\\\"\"he\"llo\"") );
        
        try {
            apacheUnquote("\"");
            fail("IllegalArgumentException expected");
        } catch(IllegalArgumentException _e) {
            assertTrue(true);
        }
        
        try {
            apacheUnquote("abc\"");
            fail("IllegalArgumentException expected");
        } catch(IllegalArgumentException _e) {
            assertTrue(true);
        }
        
        try {
            apacheUnquote("\"abc");
            fail("IllegalArgumentException expected");
        } catch(IllegalArgumentException _e) {
            assertTrue(true);
        }
    }

    @Test
    public void testCompile() {
        
        // kody \r \t \f \n \b
        assertEquals("\r \t \f \n \b", StringCompiler.compile("\\r \\t \\f \\n \\b"));
        
        // kod \\
        assertEquals("c:\\win32\\new\n", StringCompiler.compile("c:\\\\win32\\\\new\\n"));
        
        // kody dodatkowe \e \^
        assertEquals("escape \033 \033[ seqence", StringCompiler.compile("escape \\e \\^ seqence"));
        
        // poprawne sekwencje OCT
        assertEquals("N\077A\042C", StringCompiler.compile("N\\077A\\042C"));
        
        // sprawdzenie niepoprawnych sekwencji OCT
        assertEquals("N\23T\779", StringCompiler.compile("N\\23T\\779"));

    }
    
    @Test
    public void testSplitQuoted() {
        String[] a = StringCompiler.splitQuoted("\"a b\" c d e \"f g\" h");
        assertArrayEquals(new String[]{"a b", "c", "d", "e", "f g", "h"}, a);
        
        String[] b = StringCompiler.splitQuoted("  \"a b\" c d e    \"f g\"    h      ");
        assertArrayEquals(new String[]{"a b", "c", "d", "e", "f g", "h"}, b);
        
        String[] c = StringCompiler.splitQuoted("  \"a b\" c d e    \"f \\\" g\"    h      ");
        assertArrayEquals(new String[]{"a b", "c", "d", "e", "f \" g", "h"}, c);
    }

}
