/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.cryptolib.commons.utils.serialization;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Random;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.cryptolib.test.tools.utils.CommonTestDataGenerator;

public class JsonMapperTest {

    private static final int MAX_STRING_LENGTH = 20;

    private static final int MAX_INTEGER = 100000;

    private static final int LIST_SIZE = 10;

    private static String _testString;

    private static Integer _testInteger;

    private static BigInteger _testBigInteger;

    private static List<BigInteger> _testBigIntegerList;

    private static String _testBigIntegerAsString;

    private static String _anotherTestString;

    private static Integer _anotherTestInteger;

    private static String _listOfBigIntegersAsStrings;

    @BeforeClass
    public static void setUp() {

        _testString =
                CommonTestDataGenerator.getAlphanumeric(MAX_STRING_LENGTH);
        _testInteger = generateRandomInteger();
        _testBigInteger =
                new BigInteger(generateRandomInteger().toString());
        _testBigIntegerAsString = toEncodedString(_testBigInteger);
        _testBigIntegerList = new ArrayList<>();
        for (int i = 1; i <= LIST_SIZE; i++) {
            _testBigIntegerList.add(_testBigInteger.add(BigInteger
                    .valueOf(i)));
        }
        _anotherTestString =
                CommonTestDataGenerator.getAlphanumeric(MAX_STRING_LENGTH);
        _anotherTestInteger = generateRandomInteger();

        _listOfBigIntegersAsStrings = "[";
        for (int i = 0; i < (LIST_SIZE - 1); i++) {
            _listOfBigIntegersAsStrings +=
                    toEncodedString(_testBigIntegerList.get(i)) + ",";
        }
        _listOfBigIntegersAsStrings +=
                toEncodedString(_testBigIntegerList.get(LIST_SIZE - 1)) + "]";
    }

    private static String toEncodedString(BigInteger value) {
        return "\"" + Base64.getEncoder().encodeToString(value.toByteArray()) + "\"";
    }

    @Test
    public void testJsonSerializationToString() throws Exception {

        SerializableTestClass testClassOut =
                new SerializableTestClass(_testString, _testInteger,
                        _testBigInteger, _testBigIntegerList);
        testClassOut.setAnotherTestString(_anotherTestString);
        testClassOut.setAnotherTestInteger(_anotherTestInteger);

        String jsonString = testClassOut.toJson();

        Assert.assertTrue(jsonString.contains(SerializableTestClass.class
                .getSimpleName()));
        Assert.assertTrue(jsonString.contains(_testString));
        Assert.assertTrue(jsonString.contains(_testInteger.toString()));
        Assert.assertTrue(jsonString.contains(_testBigIntegerAsString));
        Assert
                .assertTrue(jsonString.contains(_listOfBigIntegersAsStrings));
        Assert.assertFalse(jsonString.contains(_anotherTestString));
        Assert.assertFalse(jsonString.contains(_anotherTestInteger
                .toString()));
    }

    @Test
    public void testJsonDeserializationFromString() throws Exception {

        SerializableTestClass testClassOut =
                new SerializableTestClass(_testString, _testInteger,
                        _testBigInteger, _testBigIntegerList);
        testClassOut.setAnotherTestString(_anotherTestString);
        testClassOut.setAnotherTestInteger(_anotherTestInteger);

        String jsonStr = testClassOut.toJson();

        SerializableTestClass testClassIn =
                new SerializableTestClass(jsonStr);

        Assert.assertEquals(testClassIn, testClassOut);
    }

    private static Integer generateRandomInteger() {

        int randomInt = new Random().nextInt(MAX_INTEGER);

        return Integer.valueOf(randomInt);
    }
}
