package eu.dnetlib.data.textengine.ws;

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

import javax.xml.namespace.QName;
import javax.xml.ws.Endpoint;
import javax.xml.ws.wsaddressing.W3CEndpointReference;
import javax.xml.ws.wsaddressing.W3CEndpointReferenceBuilder;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import eu.dnetlib.common.interfaces.ws.ServiceException;
import eu.dnetlib.data.textengine.RecognizeType;
import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
import eu.dnetlib.enabling.tools.JaxwsServiceResolverImpl;
import eu.dnetlib.resultset.impl.CreatePullRSType;
import eu.dnetlib.soap.cxf.CxfEndpointReferenceBuilder;
import eu.dnetlib.soap.cxf.JaxwsEndpointReferenceBuilder;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:junit-configurationContext.xml", "local-cxf.xml"})
public class TextEngineServiceFacadeTest{

	private static final Log log = LogFactory.getLog(TextEngineServiceFacadeTest.class);
	
	private static transient W3CEndpointReference epr;
	@SuppressWarnings("unused")
	private static transient W3CEndpointReference eprLang;
	@SuppressWarnings("unused")
	private static transient JaxwsServiceResolverImpl resolver;

	private static transient JaxwsEndpointReferenceBuilder eprBuilder;

	private static transient ResultSetService resultSetService;
	
	private transient TextEngineDataProviderImpl dataProvider;

    private final String bdId = "rs-0987";
    
	private static String rsId = "1235"; 
	
	private transient CreatePullRSType pullRsType;

	private transient TextEngineDataProviderProperties dataProvProps;

	/*
	 * initialize the whole spring-beans stuff
	 */
	@Autowired
	private TextEngineServiceFacade textEngineService;

	@BeforeClass
	public static void onlyonce(){
		resolver = new JaxwsServiceResolverImpl();
		eprBuilder = new JaxwsEndpointReferenceBuilder();
		eprBuilder.setBuilder(new CxfEndpointReferenceBuilder());		

		eprBuilder = new JaxwsEndpointReferenceBuilder();
		eprBuilder.setBuilder(new CxfEndpointReferenceBuilder());
		
		resultSetService = mock(ResultSetService.class);
		
		final Endpoint endpoint = Endpoint.publish("local://test", resultSetService);
		final Endpoint endpointLangRs = Endpoint.publish("local://testLangrs", resultSetService);
		
		//assertNotNull("check endpoint", endpoint);
		epr = eprBuilder.getEndpointReference(endpoint, rsId); 
		eprLang = eprBuilder.getEndpointReference(endpointLangRs, rsId); 

	}
	
	@Before
	public void setUp()throws Exception{
		log.debug("resService: " + resultSetService.identify());
		
		textEngineService.setServiceAddress("local://test");
		setupRs();
	}
	
	private void setupRs() throws ResultSetException{
		
		//eprInvalid = eprBuilder.getEndpointReference(endpointInvalid, rsId);
		when(resultSetService.identify()).thenReturn("foo");
		when(resultSetService.getNumberOfElements(rsId)).thenReturn(2);
		
		setupDataprovider();
	}
	
	private void setupDataprovider() throws ResultSetException{
		final int initialPageSize = 50;
		final int expiryTime = 5000;
		final String styleSheet = "";
		final int keepAliveTime = 5000;
		final int total = resultSetService.getNumberOfElements(rsId);
		dataProvider = mock(TextEngineDataProviderImpl.class);
		pullRsType = new CreatePullRSType();
		System.out.println("setup pullrstype: " + pullRsType);
		textEngineService.setDataProvider(dataProvider);
		dataProvProps = mock(TextEngineDataProviderProperties.class);
		when(dataProvider.createDataProviderProperties()).thenReturn(dataProvProps);
		when(dataProvProps.getRsMode()).thenReturn("waiting");
		when(dataProvider.createBulkData(dataProvProps)).thenReturn(bdId);
		pullRsType.setKeepAliveTime(keepAliveTime);
		pullRsType.setStyleSheet(styleSheet);
		pullRsType.setTotal(Integer.valueOf(total));
		log.debug("dataprovAddress: " + textEngineService.getServiceAddress() + " bdId: " + bdId +
				" initPageSize: " + initialPageSize + " expTime: " + expiryTime + " keepalive: " + keepAliveTime + " total: " + total);
		
	}

	@Test
	public void testIdentify(){
		  assertNotNull(textEngineService.identify());
	}
	
	@Test
	public void testRecognize()throws ServiceException{
		
		String lang = null;
		lang = textEngineService.recognize("Bitte ein Bier!", new RecognizeType());

		assertEquals("deu/ger", lang);
	}
	
	@Test (expected=ServiceException.class)
	public void testRecognizeNonExistingFile() throws ServiceException{
		String nonExistingFile = "http://nonexisting.location/blabla";
		textEngineService.recognizeFile(nonExistingFile);
		String fileNotDefined = "";
		textEngineService.recognizeFile(fileNotDefined);
	}
	
	@Test (expected=ServiceException.class)
	public void testRecognizeNotSupportedFile() throws ServiceException{
		String notSupportedMimeType = "file://" + this.getClass().getClassLoader().getResource("testdata/driverLogoSmall.png").getPath();
		textEngineService.recognizeFile(notSupportedMimeType);		
	}
	
	@Test
	public void testRecognizeFile() throws ServiceException{
		//final String expectedUndefined = "KNO";
		final String expectedENGLISH   = "eng";
		String file = "file://" + this.getClass().getClassLoader().getResource("testdata/fulltext.pdf").getPath();
		String actualLang = null;
		actualLang = textEngineService.recognizeFile(file);
		assertEquals(expectedENGLISH, actualLang);
	}
	
	@Test
	public void testRecognizePlainTextFile() throws Exception {
		String recognizedResult = null;
		String file = "file://" + this.getClass().getClassLoader().getResource("testdata/sample_txt_document_pl.txt").getPath();
		//String file = "file://" + this.getClass().getClassLoader().getResource("testdata/fulltext.pdf").getPath();
		log.debug("file: " + file);
		recognizedResult = textEngineService.recognizeFile(file);
		assertNotNull(recognizedResult);
		assertEquals("pol", recognizedResult);
	}

	
	@Test
	public void testRecognizeRS() throws ServiceException{		
		assertNotNull(epr);
		log.debug(epr.toString());
		RecognizeType recognize_type = new RecognizeType();
		W3CEndpointReference eprResult = textEngineService.recognizeRS(epr, recognize_type);
		assertNotNull(eprResult);
	}
	
	@Test (expected=ServiceException.class)
	public void testRecognizeInvalidRS() throws ServiceException{
		 final W3CEndpointReferenceBuilder W3CResultSetEPR = new W3CEndpointReferenceBuilder();

         W3CResultSetEPR.address("invalidURI");
         W3CResultSetEPR.serviceName(new QName("http://www.w3.org/2006/02/addressing/wsdl","servicename"));
         W3CResultSetEPR.endpointName(new QName("http://www.driver.org/schema","servicename"));
 
         W3CEndpointReference eprInvalid = W3CResultSetEPR.build();

		
		assertNotNull(eprInvalid);
		RecognizeType recognize_type = new RecognizeType();
		@SuppressWarnings("unused")
		W3CEndpointReference eprResult = textEngineService.recognizeRS(eprInvalid, recognize_type);
		fail("Exception should be thrown when recognizing invalid resultsetEpr");
	}
	
}
