package eu.dnetlib.data.collective.transformation.engine;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import eu.dnetlib.data.collective.transformation.VocabularyMap;
import eu.dnetlib.data.collective.transformation.VocabularyRegistry;
import eu.dnetlib.data.collective.transformation.core.xsl.ext.TransformationFunctionProxy;
import eu.dnetlib.data.collective.transformation.engine.functions.Convert;
import eu.dnetlib.data.collective.transformation.engine.functions.ProcessingException;
import eu.dnetlib.data.collective.transformation.engine.functions.RegularExpression;
import eu.dnetlib.data.collective.transformation.engine.functions.Vocabulary;
import eu.dnetlib.data.collective.transformation.rulelanguage.IRule;
import eu.dnetlib.data.collective.transformation.rulelanguage.util.FunctionCall;

//@RunWith(MockitoJUnitRunner.class)
public class PreProcessorTest {

	private transient PreProcessor preProc;
	private transient TransformationFunctionProxy functionProxy = TransformationFunctionProxy.getInstance();
	private transient Convert convertFunction;
	private transient RegularExpression regExprFunction;
	
	@Mock
	private transient FunctionCall functionCall;
	@Mock
	private transient FunctionCall fc2;
	private transient Map<String, String> paramMap = new HashMap<String, String>();
	private transient Map<String, String> paramMap2 = new HashMap<String, String>();
	
	private transient Map<String, String> nsMap = new HashMap<String, String>();
	private transient Map<String, String> staticResults = new HashMap<String, String>();
	private transient VocabularyMap vocabularyMapWrapper = new VocabularyMap();
	private transient Map<String, Vocabulary> vocabulariesMap = new HashMap<String, Vocabulary>();
	private transient Map<String, IRule> varRulesMap = new HashMap<String, IRule>();
	private transient Map<String, String> jobProperties = new HashMap<String, String>();
	@Mock
	private transient Vocabulary vocabulary;
	private final String vocabularyName = "LANG";
	private final String[] fieldValue = {"xyz"};
	private final String encodedValue = "abc";
	private final String uniqueKey = "uniqueKey-123";
	private final String uniqueKey2 = "uniqueKey-456";
	@Mock
	private transient VocabularyRegistry vocabularyRegistry;
	
	
	//@Before
	public void setUp()throws ProcessingException{
		nsMap.put("dc", "http://purl.org/dc/elements/1.1/");
		paramMap.put(Convert.paramFieldValue, "//dc:language[2]");
		paramMap.put(Convert.paramVocabularyName, "LANG");
		when(functionCall.getExternalFunctionName()).thenReturn("convert");
		when(functionCall.getParameters()).thenReturn(paramMap);
		when(functionCall.getUuid()).thenReturn(uniqueKey);
		
		paramMap2.put(RegularExpression.paramExpr1, "x");
		paramMap2.put(RegularExpression.paramExpr2, "y");
		paramMap2.put(RegularExpression.paramRegularExpr, "z");
		when(fc2.getExternalFunctionName()).thenReturn("regExpr");
		when(fc2.getParameters()).thenReturn(paramMap2);
		when(fc2.getUuid()).thenReturn(uniqueKey2);
		when(fc2.isStatic()).thenReturn(true);
		
		vocabulariesMap.put(vocabularyName, vocabulary);
		vocabularyMapWrapper.setMap(vocabulariesMap);
		when(vocabularyRegistry.getVocabularies()).thenReturn(vocabularyMapWrapper);
		when(vocabulary.getName()).thenReturn("someQuery");
		when(vocabularyRegistry.getVocabulary(vocabularyName)).thenReturn(vocabulary);
		convertFunction = new Convert();
		convertFunction.setVocabularyRegistry(vocabularyRegistry);
		//addVocabulary(vocabularyName, vocabulary);
		regExprFunction = new RegularExpression();

		preProc = new PreProcessor();		
		preProc.setFunctionProxy(functionProxy);
		preProc.setRegExprFunction(regExprFunction);
		preProc.setConvertFunction(convertFunction);
		when(vocabulary.encoding(Arrays.asList(fieldValue))).thenReturn(encodedValue);
	}
	
	// deprecated
//	@Test
//	public void testConvert(){
//		List<String> objRecords = getObjRecords();
//		assertFalse(objRecords.isEmpty());
//		preProc.preprocess(functionCall, objRecords, nsMap, staticResults, jobProperties, varRulesMap);
//		assertEquals(encodedValue, preProc.getFunctionProxy().convert(uniqueKey, 0));
//	}
	
//	@Test
//	public void testRegEpr(){
//		List<String> objRecords = getObjRecords();
//		assertFalse(objRecords.isEmpty());
//		preProc.preprocess(fc2, objRecords, nsMap, staticResults);
//		assertNotNull(preProc.getFunctionProxy().regExpr(uniqueKey2, 0));
//	}
	
	private List<String> getObjRecords(){
		List<String> objRecordList = new java.util.LinkedList<String>();
		StringBuilder builder = new StringBuilder();
		builder.append("<objectRecord>");
		builder.append(getMdRecord());
		builder.append("</objectRecord>");
		objRecordList.add(builder.toString());
		return objRecordList;
	}
	
	private String getMdRecord(){
		StringBuilder builder = new StringBuilder();
		builder.append("<record xmlns:dri=\"http://www.driver-repository.eu/namespace/dri\">");
		builder.append("<header>");
		builder.append("<dri:objIdentifier>234</dri:objIdentifier>");
		builder.append("<dri:recordIdentifier>abc</dri:recordIdentifier>");
		builder.append("<dri:dateOfCollection>2009-09-30T13:08:57Z</dri:dateOfCollection>");
		builder.append("<dri:mdFormat/>");
		builder.append("<dri:mdFormatInterpretation/>");
		builder.append("<dri:repositoryId>71f5069a-9ea2-41fa-968a-4f69a5722ad0_UmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZXMvUmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZVR5cGU=</dri:repositoryId>");
		builder.append("</header><metadata>");
		builder.append("<oai_dc:dc xmlns:oai_dc=\"http://www.openarchives.org/OAI/2.0/oai_dc/\" xmlns=\"http://www.openarchives.org/OAI/2.0/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xsi:schemaLocation=\"http://www.openarchives.org/OAI/2.0/oai_dc/  http://www.openarchives.org/OAI/2.0/oai_dc.xsd\">");
		builder.append("<dc:title>SomeTitle</dc:title>");
		builder.append("<dc:language>firstLang</dc:language>");
		builder.append("<dc:language>" + fieldValue[0] + "</dc:language>");
		builder.append("<dc:language>lastLang</dc:language>");
		builder.append("</oai_dc:dc>");
		builder.append("</metadata>");
		builder.append("</record>");
		return builder.toString();
	}
}
