/*
 * Copyright © 2016 John H Uckele. All rights reserved.
 */

package io.vivarium.serialization;

import static org.junit.Assert.assertEquals;

import java.util.LinkedList;

import org.junit.Test;

import com.google.common.collect.Lists;
import com.johnuckele.vtest.Tester;

import io.vivarium.core.Blueprint;
import io.vivarium.core.Creature;
import io.vivarium.core.Species;
import io.vivarium.core.World;
import io.vivarium.core.processor.NeuralNetwork;

public class JSONSerializationTest
{
    @Test
    public void testWorldSerializeAndDeserialize()
    {
        // Build a world with creatures
        Species species = Species.makeDefault();
        species.setNormalizeAfterMutation(Math.sqrt(42));
        species.setRandomInitialization(false);
        Blueprint blueprint = Blueprint.makeDefault();
        blueprint.setSpecies(Lists.newArrayList(species));
        World world = new World(blueprint);

        // Convert to json
        String jsonString = JSONConverter.serializerToJSONString(world);

        // Deserialize
        World deserializeWorld = JSONConverter.jsonStringToSerializerCollection(jsonString).getFirst(World.class);

        // Deep compare of creature brains
        LinkedList<Creature> originalCreatures = world.getCreatures();
        LinkedList<Creature> deserializedCreatures = deserializeWorld.getCreatures();
        Tester.equal("Creature counts should be the same", originalCreatures.size(), deserializedCreatures.size());
        for (int index = 0; index < originalCreatures.size(); index++)
        {
            Creature originalCreature = originalCreatures.get(index);
            Creature deserializedCreature = originalCreatures.get(index);
            if (originalCreature.getProcessor() instanceof NeuralNetwork)
            {
                NeuralNetwork originalCreatureProcessor = (NeuralNetwork) originalCreature.getProcessor();
                NeuralNetwork deserializedCreatureProcessor = (NeuralNetwork) deserializedCreature.getProcessor();
                double[][][] originalCreatureProcessorWeights = originalCreatureProcessor.getWeights();
                double[][][] deserializedCreatureProcessorWeights = deserializedCreatureProcessor.getWeights();
                compareNeuralNetworkWeights(originalCreatureProcessorWeights, deserializedCreatureProcessorWeights);
                assertEquals(Math.sqrt(42), originalCreatureProcessor.getGenomeLength(), 0.0000000001);
                assertEquals(Math.sqrt(42), deserializedCreatureProcessor.getGenomeLength(), 0.0000000001);
            }
        }
    }

    private void compareNeuralNetworkWeights(double[][][] weights1, double[][][] weights2)
    {
        for (int i = 0; i < weights1.length; i++)
        {
            for (int j = 0; j < weights1[i].length; j++)
            {
                for (int k = 0; k < weights1[i][j].length; k++)
                {
                    assertEquals(weights1[i][j][k], weights2[i][j][k], 0);
                }
            }
        }

    }
}

@@ -143,38 +143,8 @@
 s;%0A%0A
-import java.util.LinkedList;%0A%0A
 impo
@@ -162,16 +162,16 @@
 t.Test;%0A
+
 %0Aimport 
@@ -206,44 +206,8 @@
 sts;
-%0Aimport com.johnuckele.vtest.Tester;
 %0A%0Aim
@@ -243,42 +243,8 @@
 nt;%0A
-import io.vivarium.core.Creature;%0A
 impo
@@ -306,57 +306,8 @@
 rld;
-%0Aimport io.vivarium.core.processor.NeuralNetwork;
 %0A%0Apu
@@ -1033,1835 +1033,65 @@
  of 
-creature brains%0A        LinkedList%3CCreature%3E originalCreatures = world.getCreatures();%0A        LinkedList%3CCreature%3E deserializedCreatures = deserializeWorld.getCreatures();%0A        Tester.equal(%22Creature counts should be the same%22, originalCreatures.size(), deserializedCreatures.size());%0A        for (int index = 0; index %3C originalCreatures.size(); index++)%0A        %7B%0A            Creature originalCreature = originalCreatures.get(index);%0A            Creature deserializedCreature = originalCreatures.get(index);%0A            if (originalCreature.getProcessor() instanceof NeuralNetwork)%0A            %7B%0A                NeuralNetwork originalCreatureProcessor = (NeuralNetwork) originalCreature.getProcessor();%0A                NeuralNetwork deserializedCreatureProcessor = (NeuralNetwork) deserializedCreature.getProcessor();%0A                double%5B%5D%5B%5D%5B%5D originalCreatureProcessorWeights = originalCreatureProcessor.getWeights();%0A                double%5B%5D%5B%5D%5B%5D deserializedCreatureProcessorWeights = deserializedCreatureProcessor.getWeights();%0A                compareNeuralNetworkWeights(originalCreatureProcessorWeights, deserializedCreatureProcessorWeights);%0A                assertEquals(Math.sqrt(42), originalCreatureProcessor.getGenomeLength(), 0.0000000001);%0A                assertEquals(Math.sqrt(42), deserializedCreatureProcessor.getGenomeLength(), 0.0000000001);%0A            %7D%0A        %7D%0A    %7D%0A%0A    private void compareNeuralNetworkWeights(double%5B%5D%5B%5D%5B%5D weights1, double%5B%5D%5B%5D%5B%5D weights2)%0A    %7B%0A        for (int i = 0; i %3C weights1.length; i++)%0A        %7B%0A            for (int j = 0; j %3C weights1%5Bi%5D.length; j++)%0A            %7B%0A                for (int k = 0; k %3C weights1%5Bi%5D%5Bj%5D.length; k++)%0A                %7B%0A                    assertEquals(weights1%5Bi%5D%5Bj%5D%5Bk%5D, weights2%5Bi%5D%5Bj%5D%5Bk%5D, 0);%0A                %7D%0A            %7D%0A        %7D%0A
+the worlds%0A        assertEquals(world, deserializeWorld);
 %0A   

Switch comparison to use deep auto-generated comparisons.