package eu.dnetlib.contract.marshall;

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

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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


import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.CompactWriter;
import com.thoughtworks.xstream.io.xml.DomDriver;

import eu.dnetlib.contract.cp.AbstractCheckPoint;
import eu.dnetlib.contract.cp.EntryCheckPoint;
import eu.dnetlib.contract.cp.ICheckPoint;
import eu.dnetlib.resultset.CreatePullRSType;

/**
 * XStream library test incubator.
 * @author mhorst
 *
 */
public class XStreamTest {

	public final static String ALIAS_EntryCheckPointObject = "EntryCheckPointObject";
	
	XStream xStream = null; 
	
	@Before
	public void init() {
		xStream = new XStream(new DomDriver());
		xStream.processAnnotations(EntryCheckPoint.class);
		xStream.processAnnotations(AbstractCheckPoint.class);
//		eventually use this instead of annotations
//		xStream.alias(ALIAS_EntryCheckPointObject, EntryCheckPointObject.class);
//		xStream.useAttributeFor(EntryCheckPointObject.class, "className");
//		xStream.useAttributeFor(EntryCheckPointObject.class, "methodName");
//		no need for status persistence
//		xStream.omitField(AbstractCheckPointObject.class, "status");
	}
	
	@SuppressWarnings("unchecked")
	@Test
	public void testCheckPointSerialization() {
		List<ICheckPoint<?>> sourceList = prepareCheckPoints();
		String xmlContent = xStream.toXML(sourceList);
		System.out.println(xmlContent);
		List<ICheckPoint<?>> resultList = (List<ICheckPoint<?>>) xStream.fromXML(xmlContent);
		assertNotNull(resultList);
		String xmlContent2 = xStream.toXML(resultList);
//		System.out.println(xmlContent);
		assertEquals(xmlContent, xmlContent2);
	}
	
	@Test
	public void testCheckPointSerializationInOneLine() {
		List<ICheckPoint<?>> sourceList = prepareCheckPoints();
		String xmlContent = xStream.toXML(sourceList);
		assertTrue(xmlContent.indexOf('\n')<xmlContent.length()-1);
		StringWriter strWriter = new StringWriter();
		xStream.marshal(sourceList, new CompactWriter(strWriter));
		System.out.println(strWriter.toString());
		assertTrue(strWriter.toString().indexOf('\n')==-1);
	}
	
//	@Test 
	public void testMapSerialization() {
		Map<String, Integer> map = new HashMap<String, Integer>();
		map.put("aaa", 111);
		map.put("bbb", 222);
		map.put("ccc", 333);
		String xmlContent = xStream.toXML(map);
		assertNotNull(xmlContent);
		System.out.println("map:\n"+xmlContent);
	}
	
//	@Test 
	public void testCollectionSerialization() {
		Collection<String> col = new ArrayList<String>();
		col.add("aaa");
		col.add("bbb");
		col.add("ccc");
		String xmlContent = xStream.toXML(col);
		assertNotNull(xmlContent);
		System.out.println("collection:\n"+xmlContent);
	}
	
//	@Test 
	public void testArraySerialization() {
		String[] array = new String[] {"aaa","bbb","ccc"};
		String xmlContent = xStream.toXML(array);
		assertNotNull(xmlContent);
		System.out.println("array:\n"+xmlContent);
	}
	
	@Test 
	public void testSimpleStringObjectBuilder() {
		Object result = xStream.fromXML("<string>someValue</string>");
		assertNotNull(result);
		System.out.println("string value: "+result);
		result = xStream.fromXML("<java.lang.String>someValue</java.lang.String>");
		assertNotNull(result);
		System.out.println("string value: "+result);
	}
	
	List<ICheckPoint<?>> prepareCheckPoints() {
		List<ICheckPoint<?>> checkPoints = new ArrayList<ICheckPoint<?>>();
		EntryCheckPoint checkPoint = new EntryCheckPoint();
//		indexLookup checkPoint
//		allowing null className
		checkPoint.setClassName("pl.edu.icm.index.IIndexService");
		checkPoint.setMethodName("indexLookup");
		checkPoint.setAttrsWithStrictFlag(
				new Object[] {"id1234", "some query", "DMF", "index"}, true);
		checkPoints.add(checkPoint);
//		createPullRS checkPoint
		checkPoint = new EntryCheckPoint();
		checkPoint.setClassName(null);
		checkPoint.setMethodName("createPullRS");
//		setting null for the values that are not important (strictChecking set to false);
//		checking createPullRSType
		CreatePullRSType createPullRSType = new CreatePullRSType();
		createPullRSType.setKeepAliveTime(1800);
		createPullRSType.setTotal(0);
		checkPoint.setAttrsWithStrictFlag(
				new Object[] {null, null, null, null, createPullRSType}, false);
		checkPoint.getArgsStrictChecking()[4] = true;
		checkPoints.add(checkPoint);
		return checkPoints;
	}
}
