package eu.dnetlib.enabling.resultset; // NOPMD

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.io.StringWriter;
import java.util.List;

import javax.xml.transform.TransformerConfigurationException;
import javax.xml.ws.wsaddressing.W3CEndpointReference;

import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import com.google.common.collect.Lists;

import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
import eu.dnetlib.enabling.tools.ServiceResolver;

/**
 * test xslt resultset.
 *
 * @author marko
 *
 */
@RunWith(MockitoJUnitRunner.class)
public class XSLTMappedResultSetFactoryTest {

	/**
	 * instance under test.
	 */
	private transient XSLTMappedResultSetFactory factory;

	/**
	 * resultset factory mock.
	 */
	@Mock
	private transient ResultSetFactory resultSetFactory;

	/**
	 * service resolver.
	 */
	@Mock
	private transient ServiceResolver serviceResolver;

	/**
	 * resultset service mock.
	 */
	@Mock
	private transient ResultSetService resultSetService;
	
	/**
	 * underlying resultSet mock
	 */
	@Mock
	private transient ResultSet resultSet;

	/**
	 * Common setup.
	 *
	 */
	@Before
	public void setUp() {
		factory = new XSLTMappedResultSetFactory();
		factory.setResultSetFactory(resultSetFactory);
		factory.setServiceResolver(serviceResolver);
	}

	/**
	 * test invalid xslt.
	 *
	 * @throws TransformerConfigurationException
	 *             could happen
	 */
	@Test(expected = IllegalStateException.class)
	public void testInvalidXslt() throws TransformerConfigurationException {
		factory.createMappedResultSet(null, "<bla/>");
	}

	/**
	 * test xslt.
	 *
	 * @throws TransformerConfigurationException
	 *             could happen
	 * @throws IOException
	 *             could happen
	 * @throws ResultSetException mock
	 */
	@Test
	public void testXslt() throws TransformerConfigurationException, IOException, ResultSetException {
		when(serviceResolver.getService(eq(ResultSetService.class), (W3CEndpointReference) anyObject())).thenReturn(resultSetService);
		when(serviceResolver.getResourceIdentifier((W3CEndpointReference) anyObject())).thenReturn("123");

		//when(resultSetService.getNumberOfElements(anyString())).thenReturn(1);
		when(resultSetService.getResult("123", 1, 1, "waiting")).thenReturn(Lists.newArrayList("<first>something</first>"));
		when(resultSetService.getRSStatus("123")).thenReturn("closed");
		
		when(resultSet.isOpen()).thenReturn(true);
		
		final StringWriter xsltSource = new StringWriter();
		IOUtils.copy(getClass().getResourceAsStream("test.xsl"), xsltSource);
		factory.createMappedResultSet(null, xsltSource.toString());

		verify(resultSetFactory, times(1)).createResultSet(argThat(new ArgumentMatcher<ResultSetListener>() {

			@Override
			public boolean matches(final ResultSetListener argument) {
				final MappedResultSet listener = (MappedResultSet) argument;
				listener.setResultSet(resultSet);
				final List<String> res = listener.getResult(1, 1);

				assertNotNull("null result", res);
				assertFalse("empty result", res.isEmpty());

				assertNotNull("null element", res.get(0));

				assertTrue("transformed correctly", res.get(0).contains("<second>something</second>"));

				return true;
			}
		}));
	}

}
