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

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

import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;


import org.dom4j.DocumentException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;

import eu.dnetlib.common.profile.Resource;
import eu.dnetlib.common.profile.ResourceDao;
import eu.dnetlib.data.collective.transformation.rulelanguage.Argument;
import eu.dnetlib.data.collective.transformation.rulelanguage.Argument.Type;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class RetrieveValueTest {

	private static final String profileId = "profileId-123"; 
	private static final String profileIdXpath = "//someXpathProfileId"; // "concat('collection(&apos;/db/DRIVER/RepositoryServiceResources&apos;)//RESOURCE_PROFILE[.//EXTRA_FIELDS/FIELD[key=&quot;NamespacePrefix&quot;][value=&quot;', //someXpathProfileId, '&quot;]]')"; 
	private static final String xpathExpr = "//someXpath";
	private static final String profileFieldValue = "someValue";
	private transient RetrieveValue retrieveValueFunc;
	
	@Mock
	private transient ResourceDao resourceDao;
	@Mock
	private transient Resource resource;
	
	@Before
	public void setUp(){
		try{
			//when(resourceDao.getResourceByQuery(profileId)).thenReturn(resource);
			when(resourceDao.getResource(profileId)).thenReturn(resource);			
		}catch(Exception e){
			e.printStackTrace();
		}		
		when(resource.getValue(xpathExpr)).thenReturn(profileFieldValue);
		retrieveValueFunc = new RetrieveValue();
		retrieveValueFunc.setResourceDao(resourceDao);
	}
	
	@Test
	public void testValueFromProfileByValue()throws ProcessingException, DocumentException{
		String record = "<objectrecord><someXpathProfileId>" + profileId + "</someXpathProfileId></objectrecord>";
		List<Argument> paramList = new LinkedList<Argument>();
		paramList.add(new Argument(Type.VALUE, profileId));
		paramList.add(new Argument(Type.INPUTFIELD, xpathExpr));
		assertEquals(profileFieldValue, retrieveValueFunc.executeSingleValue(RetrieveValue.FUNCTION.PROFILEFIELD.name(), paramList, record, new LinkedHashMap<String, String>()));
	}

	@Test
	public void testValueFromProfileByXpath()throws ProcessingException, DocumentException{
		String record = "<objectrecord><someXpathProfileId>" + profileId + "</someXpathProfileId></objectrecord>";
		List<Argument> paramList = new LinkedList<Argument>();
		paramList.add(new Argument(Type.INPUTFIELD, profileIdXpath));
		paramList.add(new Argument(Type.INPUTFIELD, xpathExpr));
		assertEquals(profileFieldValue, retrieveValueFunc.executeSingleValue(RetrieveValue.FUNCTION.PROFILEFIELD.name(), paramList, record, new LinkedHashMap<String, String>()));
	}

	@Test(expected = IllegalArgumentException.class)
	public void testInvalidFunctionName()throws ProcessingException, DocumentException{
		List<Argument> paramList = new LinkedList<Argument>();
		paramList.add(new Argument(Type.VALUE, profileId));
		paramList.add(new Argument(Type.INPUTFIELD, xpathExpr));
		assertEquals(profileFieldValue, retrieveValueFunc.executeSingleValue("someInvalidFunctionName", paramList, "", new LinkedHashMap<String, String>()));
	}
	
	@Test(expected = ProcessingException.class)
	public void testInvalidProfileId()throws ProcessingException, DocumentException{
		String profileId = "invalidProfileId";
		String xpathExpr = "//someExpr";
		
		try {
			when(resourceDao.getResource(profileId)).thenReturn(null);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		List<Argument> paramList = new LinkedList<Argument>();
		paramList.add(new Argument(Type.VALUE, profileId));
		paramList.add(new Argument(Type.INPUTFIELD, xpathExpr));
		assertEquals(profileFieldValue, retrieveValueFunc.executeSingleValue(RetrieveValue.FUNCTION.PROFILEFIELD.name(), paramList, "", new LinkedHashMap<String, String>()));
	}
}
