package pl.edu.pw.mini.jk.sg.gteval;

import scala.Option;
import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;

import org.junit.Before;
import org.junit.Test;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;

import pl.edu.pw.mini.jk.sg.game.NormalizableFactory;
import pl.edu.pw.mini.jk.sg.game.configuration.DiscreteProbabilityFunction;
import pl.edu.pw.mini.jk.sg.game.configuration.Edge;
import pl.edu.pw.mini.jk.sg.game.configuration.GraphDescription;
import pl.edu.pw.mini.jk.sg.game.configuration.StaticGameConfiguration;
import pl.edu.pw.mini.jk.sg.game.graph.advanceable.AdvanceableGraphGameConfiguration;
import pl.edu.pw.mini.jk.sg.game.graph.advanceable.AdvanceableStateGraphGame;
import pl.edu.pw.mini.jk.sg.game.graph.moves.many.advanceable.ManyMovesAdvanceableStateGame;
import pl.edu.pw.mini.jk.sg.game.graph.moves.many.advanceable.SingleUnitDestination;
import pl.edu.pw.mini.jk.sg.game.graph.NormalizableAdvanceableStateGraphGameFactory;
import pl.edu.pw.mini.jk.sg.game.graph.NormalizableManyMovesAdvanceableStateGameFactory;
import pl.edu.pw.mini.jk.sg.game.graph.moves.single.DesiredConfigurationMove;
import pl.edu.pw.mini.jk.sg.opt.util.GameUtil;


public class AppTest { 
    private NormalizableFactory<DesiredConfigurationMove, DesiredConfigurationMove, AdvanceableStateGraphGame> gameFactory;
    private NormalizableFactory<SingleUnitDestination, SingleUnitDestination, ManyMovesAdvanceableStateGame> gameFactoryMulti;

    
	private static StaticGameConfiguration getGameConfiguration() {
		java.util.List<Edge> edges = new ArrayList<>();

		for (int i = 0; i < 4; i++) {
			edges.add(new Edge(i, 4));
			edges.add(new Edge(4, i));
		}

		return  new StaticGameConfiguration(new GraphDescription(5, edges), Arrays.asList(2, 3), Arrays.asList(1),
				new int[][] { { 10 }, { 15 } }, new int[][] { { 8 }, { 10 } },
				new int[][] { { 1 }, { 2 }, { 3 }, { 4 }, { 5 } }, new int[][] { { 5 }, { 4 }, { 3 }, { 2 }, { 1 } }, 1,
						    3, DiscreteProbabilityFunction.instance(), 0, 0);
	}


	@Before
	public void setUp() throws Exception {
	    gameFactory = new NormalizableAdvanceableStateGraphGameFactory(new AdvanceableGraphGameConfiguration(getGameConfiguration(), 2), Option.empty(), false);
	    gameFactoryMulti = new NormalizableManyMovesAdvanceableStateGameFactory(new AdvanceableGraphGameConfiguration(getGameConfiguration(), 2), null, false);
	}

	@Test
	public void testGetDefenderPayoff() {
		
		Map<ImmutableList<DesiredConfigurationMove>, Double> dmp = ImmutableMap.of(
				ImmutableList.of(new DesiredConfigurationMove(new int[] {0,0,4}), 
						new DesiredConfigurationMove(new int[] {0,0,4})),
				Double.valueOf(0.5),
				ImmutableList.of(new DesiredConfigurationMove(new int[] {0,0,0}), 
						new DesiredConfigurationMove(new int[] {0,0,0})),
				Double.valueOf(0.5)
				);
		assertEquals(-10, PayoffUtils.getDefenderPayoff(GameUtil.calculateGameMatrices(gameFactory, 2), dmp), 1e-6);
	}

    	@Test
	public void testGetDefenderPayoffMany() {
		
		Map<ImmutableList<SingleUnitDestination>, Double> dmp = ImmutableMap.of(
											   ImmutableList.of(new SingleUnitDestination(0), new SingleUnitDestination(0), new SingleUnitDestination(4), new SingleUnitDestination(0), new SingleUnitDestination(0), new SingleUnitDestination(4)							    ),
											   Double.valueOf(0.5),
				ImmutableList.of(new SingleUnitDestination(0), new SingleUnitDestination(0), new SingleUnitDestination(0), new SingleUnitDestination(0), new SingleUnitDestination(0), new SingleUnitDestination(0)							    ),
				Double.valueOf(0.5)
				);
		assertEquals(-10, PayoffUtils.getDefenderPayoff(GameUtil.calculateGameMatrices(gameFactoryMulti, 2), dmp), 1e-6);
	}

    
}
