package uk.gov.register.util;

import com.fasterxml.jackson.core.JsonParseException;
import org.junit.Test;
import uk.gov.register.util.CanonicalJsonMapper;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;

public class CanonicalJsonMapperTest {
    public final CanonicalJsonMapper mapper = new CanonicalJsonMapper();

    @Test
    public void shouldAcceptJson() throws Exception {
        byte[] jsonBytes = "{\"foo\":\"bar\"}".getBytes();

        byte[] canonicalBytes = mapper.writeToBytes(mapper.readFromBytes(jsonBytes));
        
        assertThat(canonicalBytes, equalTo(jsonBytes));
    }

    @Test(expected = JsonParseException.class)
    public void shouldNotAcceptJsonWithUnbalancedBraces() throws Exception {
        byte[] jsonBytes = "{\"foo\":\"bar\"".getBytes();

        mapper.readFromBytes(jsonBytes);
    }

    @Test(expected = JsonParseException.class)
    public void shouldNotAcceptJsonWithUnescapedQuoteMarks() throws Exception {
        byte[] jsonBytes = "{\"foo\":\"\"\"}".getBytes();

        mapper.readFromBytes(jsonBytes);
    }

    @Test
    public void shouldTransformJsonToCanonicalMapFieldOrder() throws Exception {
        byte[] originalBytes = "{\"bbb\":5,\"ccc\":\"foo\",\"aaa\":\"bar\"}".getBytes();
        byte[] sortedBytes = "{\"aaa\":\"bar\",\"bbb\":5,\"ccc\":\"foo\"}".getBytes();

        byte[] canonicalBytes = mapper.writeToBytes(mapper.readFromBytes(originalBytes));

        assertThat(canonicalBytes, equalTo(sortedBytes));
    }

    @Test
    public void shouldStripWhitespaceFromJson() throws Exception {
        byte[] originalBytes = "{   \"  foo  \" \t\n : \r \"   \"}".getBytes();
        byte[] strippedBytes = "{\"  foo  \":\"   \"}".getBytes();

        byte[] canonicalBytes = mapper.writeToBytes(mapper.readFromBytes(originalBytes));

        assertThat(canonicalBytes, equalTo(strippedBytes));
    }

    @Test
    public void shouldTransformSimpleUnicodeEscapesToUnescapedValues() throws Exception {
        byte[] originalBytes = "{\"\\u0066\\u006f\\u006f\":\"bar\\n\"}".getBytes();
        byte[] unescapedBytes = "{\"foo\":\"bar\\n\"}".getBytes();

        byte[] canonicalBytes = mapper.writeToBytes(mapper.readFromBytes(originalBytes));

        assertThat(canonicalBytes, equalTo(unescapedBytes));
    }

    @Test
    public void shouldTransformComplexUnicodeEscapesToUnescapedValues() throws Exception {
        // uses MUSICAL SYMBOL G CLEF (U+1D11E) as a non-BMP character
        byte[] originalBytes = "{\"g-clef\":\"\\uD834\\uDD1E\"}".getBytes(); // note this is unicode escaped in the JSON
        byte[] unescapedBytes = String.format("{\"g-clef\":\"%s\"}", new String(Character.toChars(0x0001D11E))).getBytes();

        byte[] canonicalBytes = mapper.writeToBytes(mapper.readFromBytes(originalBytes));

        assertThat(canonicalBytes, equalTo(unescapedBytes));
    }

    @Test
    public void shouldTransformComplexUnicodeEscapesInKeysToUnescapedValues() throws Exception {
        // uses MUSICAL SYMBOL G CLEF (U+1D11E) as a non-BMP character
        byte[] originalBytes = "{\"\\uD834\\uDD1E\":\"g-clef\"}".getBytes(); // note this is unicode escaped in the JSON
        byte[] unescapedBytes = String.format("{\"%s\":\"g-clef\"}", new String(Character.toChars(0x0001D11E))).getBytes();

        byte[] canonicalBytes = mapper.writeToBytes(mapper.readFromBytes(originalBytes));

        assertThat(canonicalBytes, equalTo(unescapedBytes));
    }
}

@@ -105,55 +105,49 @@
 st;%0A
+%0A
 import 
-uk.gov.register.util.CanonicalJsonMapper
+java.nio.charset.StandardCharsets
 ;%0A%0Ai
@@ -3484,11 +3484,1152 @@
 );%0A    %7D
+%0A%0A    @Test%0A    public void shouldTransformUnicodeEscapesToShortEscapes() throws Exception %7B%0A        byte%5B%5D originalBytes = %22%7B%5C%22%5C%5Cu0008%5C%5Cu000c%5C%5Cu000a%5C%5Cu000d%5C%5Cu0009%5C%22:%5C%22%5C%5Cu0022%5C%5Cu005c%5C%22%7D%22.getBytes(); // note this is unicode escaped in the JSON%0A        byte%5B%5D reescapedBytes = %22%7B%5C%22%5C%5Cb%5C%5Cf%5C%5Cn%5C%5Cr%5C%5Ct%5C%22:%5C%22%5C%5C%5C%22%5C%5C%5C%5C%5C%22%7D%22.getBytes();%0A%0A        byte%5B%5D canonicalBytes = mapper.writeToBytes(mapper.readFromBytes(originalBytes));%0A%0A        assertThat(new String(canonicalBytes, StandardCharsets.UTF_8), equalTo(new String(reescapedBytes, StandardCharsets.UTF_8)));%0A    %7D%0A%0A    @Test%0A    public void shouldPreserveUnicodeEscapesForUncommonControlCharactersAndCapitalizeHexDigits() throws Exception %7B%0A        byte%5B%5D originalBytes = %22%7B%5C%22%5C%5Cu0000%5C%5Cu0001%5C%5Cu000b%5C%5Cu0012%5C%5Cu0015%5C%22:%5C%22%5C%22%7D%22.getBytes(); // note this is unicode escaped in the JSON%0A        byte%5B%5D reescapedBytes = %22%7B%5C%22%5C%5Cu0000%5C%5Cu0001%5C%5Cu000B%5C%5Cu0012%5C%5Cu0015%5C%22:%5C%22%5C%22%7D%22.getBytes();%0A%0A        byte%5B%5D canonicalBytes = mapper.writeToBytes(mapper.readFromBytes(originalBytes));%0A%0A        assertThat(new String(canonicalBytes, StandardCharsets.UTF_8), equalTo(new String(reescapedBytes, StandardCharsets.UTF_8)));%0A    %7D
 %0A%7D%0A

add more tests to CanonicalJsonMapperTest