package eu.dnetlib.contract.cp;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

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

import eu.dnetlib.contract.conv.ComplexObjectsXStreamConverter;
import eu.dnetlib.contract.conv.IComplexObectToStringConverter;
import eu.dnetlib.contract.cp.EntryCheckPoint;
import eu.dnetlib.contract.cp.ResultCheckPoint;
import eu.dnetlib.contract.cp.comp.ComparatorManager;
import eu.dnetlib.contract.node.ContractDefinitionNodeInitializer;
import eu.dnetlib.contract.node.IContractDefinitionNode;
import eu.dnetlib.contract.node.RANDDefinitionNode;
import eu.dnetlib.contract.node.SEQDefinitionNode;


/**
 * {@link ContractDefinitionNodeInitializer} module test class.
 * @author mhorst
 *
 */
public class ContractDefinitionNodeInitializerTest {

	private ContractDefinitionNodeInitializer initializer = null;
	private ComparatorManager comparatorManager = null;
	private IComplexObectToStringConverter converter = null;
	
	
	@Before
	public void init() {
		initializer = new ContractDefinitionNodeInitializer();
		comparatorManager = new ComparatorManager();
		initializer.setComparatorManager(comparatorManager);
		converter = new ComplexObjectsXStreamConverter();
		initializer.setConverter(converter);
	}
	
	@Test
	public void testInitializeCheckPoint() {
		EntryCheckPoint cp = new EntryCheckPoint();
		initializer.initializeNode(cp);
		assertNotNull(cp.getComparatorManager());
		assertTrue(comparatorManager == cp.getComparatorManager());
		assertNotNull(cp.getConverter());
		assertTrue(converter == cp.getConverter());
		assertTrue(null == cp.getParentNode());
	}
	
	@Test
	public void testInitializeComplex() {
		List<IContractDefinitionNode> cps = new ArrayList<IContractDefinitionNode>();
		ResultCheckPoint cp1 = new ResultCheckPoint();
		ResultCheckPoint cp2 = new ResultCheckPoint();
		ResultCheckPoint cp3 = new ResultCheckPoint();
		cps.add(cp1);
		cps.add(cp2);
		cps.add(cp3);
		SEQDefinitionNode nodeSeq1 = new SEQDefinitionNode(cps);
		SEQDefinitionNode nodeSeq2 = new SEQDefinitionNode(
				new ArrayList<IContractDefinitionNode>());
		
		List<IContractDefinitionNode> randCps = new ArrayList<IContractDefinitionNode>();
		ResultCheckPoint randCp1 = new ResultCheckPoint();
		ResultCheckPoint randCp2 = new ResultCheckPoint();
		SEQDefinitionNode randSeq = new SEQDefinitionNode(
				new ArrayList<IContractDefinitionNode>());
		randCps.add(randCp1);
		randCps.add(randCp2);
		randCps.add(randSeq);
		RANDDefinitionNode randNode = new RANDDefinitionNode(randCps);
		
		List<IContractDefinitionNode> seqs = new ArrayList<IContractDefinitionNode>();
		seqs.add(nodeSeq1);
		seqs.add(nodeSeq2);
		seqs.add(randNode);

		SEQDefinitionNode rootNode = new SEQDefinitionNode(seqs);
		initializer.initializeNode(rootNode);
		
		assertTrue(comparatorManager == cp1.getComparatorManager());
		assertTrue(converter == cp1.getConverter());
		assertTrue(nodeSeq1 == cp1.getParentNode());
		assertTrue(null == cp1.getPrevNode());
		assertTrue(cp1.getNextNode() == cp2);
		
		assertTrue(comparatorManager == cp2.getComparatorManager());
		assertTrue(converter == cp2.getConverter());
		assertTrue(nodeSeq1 == cp2.getParentNode());
		assertTrue(cp1 == cp2.getPrevNode());
		assertTrue(cp2.getNextNode() == cp3);
		
		assertTrue(comparatorManager == cp3.getComparatorManager());
		assertTrue(converter == cp3.getConverter());
		assertTrue(nodeSeq1 == cp3.getParentNode());
		assertTrue(cp2 == cp3.getPrevNode());
		assertTrue(cp3.getNextNode() == null);
		
		assertTrue(comparatorManager == randCp1.getComparatorManager());
		assertTrue(converter == randCp1.getConverter());
		assertTrue(randNode == randCp1.getParentNode());
		assertTrue(null == randCp1.getPrevNode());
		assertTrue(randCp1.getNextNode() == null);
		
		assertTrue(comparatorManager == randCp2.getComparatorManager());
		assertTrue(converter == randCp2.getConverter());
		assertTrue(randNode == randCp2.getParentNode());
		assertTrue(null == randCp2.getPrevNode());
		assertTrue(randCp2.getNextNode() == null);
		
		assertTrue(randNode == randSeq.getParentNode());
		assertTrue(null == randSeq.getPrevNode());
		assertTrue(randSeq.getNextNode() == null);
		
		assertTrue(rootNode == nodeSeq1.getParentNode());
		assertTrue(null == nodeSeq1.getPrevNode());
		assertTrue(nodeSeq1.getNextNode() == nodeSeq2);
		
		assertTrue(rootNode == nodeSeq2.getParentNode());
		assertTrue(nodeSeq1 == nodeSeq2.getPrevNode());
		assertTrue(nodeSeq2.getNextNode() == randNode);
		
		assertTrue(rootNode == randNode.getParentNode());
		assertTrue(nodeSeq2 == randNode.getPrevNode());
		assertTrue(randNode.getNextNode() == null);
		
		assertTrue(null == rootNode.getParentNode());
		assertTrue(null == rootNode.getPrevNode());
		assertTrue(rootNode.getNextNode() == null);
	}
	
	@Test
	public void testInitializeNodePositionIdentifiers() {
		List<IContractDefinitionNode> cps = new ArrayList<IContractDefinitionNode>();
		ResultCheckPoint cp1 = new ResultCheckPoint();
		ResultCheckPoint cp2 = new ResultCheckPoint();
		ResultCheckPoint cp3 = new ResultCheckPoint();
		cps.add(cp1);
		cps.add(cp2);
		cps.add(cp3);
		SEQDefinitionNode nodeSeq1 = new SEQDefinitionNode(cps);
		SEQDefinitionNode nodeSeq2 = new SEQDefinitionNode(
				new ArrayList<IContractDefinitionNode>());
		
		List<IContractDefinitionNode> randCps = new ArrayList<IContractDefinitionNode>();
		ResultCheckPoint randCp1 = new ResultCheckPoint();
		ResultCheckPoint randCp2 = new ResultCheckPoint();
		SEQDefinitionNode randSeq = new SEQDefinitionNode(
				new ArrayList<IContractDefinitionNode>());
		randCps.add(randCp1);
		randCps.add(randCp2);
		randCps.add(randSeq);
		RANDDefinitionNode randNode = new RANDDefinitionNode(randCps);
		
		List<IContractDefinitionNode> seqs = new ArrayList<IContractDefinitionNode>();
		seqs.add(nodeSeq1);
		seqs.add(nodeSeq2);
		seqs.add(randNode);

		SEQDefinitionNode rootNode = new SEQDefinitionNode(seqs);
		initializer.initializeNode(rootNode);
		
		assertEquals("seq", rootNode.getNodePositionIdentifier());
		
		assertEquals("seq[0].seq", nodeSeq1.getNodePositionIdentifier());
		assertEquals("seq[1].seq", nodeSeq2.getNodePositionIdentifier());
		assertEquals("seq[2].rand", randNode.getNodePositionIdentifier());
		
		assertEquals("seq[0].seq[0].ResultCheckPoint", cp1.getNodePositionIdentifier());
		assertEquals("seq[0].seq[1].ResultCheckPoint", cp2.getNodePositionIdentifier());
		assertEquals("seq[0].seq[2].ResultCheckPoint", cp3.getNodePositionIdentifier());
		
		assertEquals("seq[2].rand[0].ResultCheckPoint", randCp1.getNodePositionIdentifier());
		assertEquals("seq[2].rand[1].ResultCheckPoint", randCp2.getNodePositionIdentifier());
		assertEquals("seq[2].rand[2].seq", randSeq.getNodePositionIdentifier());
	}
}
