package eu.dnetlib.enabling.is.lookup;

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

import java.util.Collections;
import java.util.List;

import javax.annotation.Resource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.wsaddressing.W3CEndpointReference;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpDocumentNotFoundException;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
import eu.dnetlib.enabling.is.store.rmi.ISStoreException;
import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
import eu.dnetlib.enabling.tools.ServiceLocator;
import eu.dnetlib.enabling.tools.ServiceResolver;
import eu.dnetlib.test.AbstractIntegrationContainerTest;

/**
 * lookup client test. This test case performs various calls to a living the ISLookUpService using real rmi (SOAP)
 * invocations, communicating also with the resultset and store and possibly other services along the way.
 *
 *
 * @author marko
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
public class ISLookUpServiceClientTest extends AbstractIntegrationContainerTest {

	/**
	 * logger.
	 */
	private static final Log log = LogFactory.getLog(ISLookUpServiceClientTest.class);

	/**
	 * lookup service locator.
	 */
	@Resource(name = "lookUpLocator")
	private transient ServiceLocator<ISLookUpService> lookupLocator;

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

	/**
	 * common init.
	 */
	@Before
	public void setUp() {
		log.debug("setting up islookup client");
	}

	/**
	 * test client.
	 *
	 * @throws InterruptedException
	 *             happens
	 */
	@Test
	public void testLookUpClient() throws InterruptedException {
		log.debug("testing is lookup client");

		assertNotNull("check locator", lookupLocator);

		final ISLookUpService isLookUp = lookupLocator.getService();

		assertEquals("check identify", "eu.dnetlib.enabling.is.lookup.ISLookUpServiceImpl", isLookUp.identify());
	}

	/**
	 * test a simple xquery which returns a static result.
	 *
	 * @throws ISLookUpException
	 *             shouldn't happen
	 * @throws ISStoreException
	 *             shouldn't happen
	 */
	@Test
	public void testLookUpXQuery() throws ISLookUpException, ISStoreException {
		final String res = lookupLocator.getService().getResourceProfileByQuery("for $x in collection('') return 'wow'");
		assertEquals("check xquery result", "wow", res);
	}

	/**
	 * runs some queries on the TestResourceType profiles registered at startup.
	 *
	 * @throws ISLookUpException
	 *             shoudn't happen
	 * @throws ISStoreException
	 *             shoudn't happen
	 */
	@Test
	public void testLookUpRealProfiles() throws ISLookUpException, ISStoreException {
		final List<String> res = lookupLocator.getService().quickSearchProfile(
				"for $x in collection('/db/DRIVER/TestResources/TestResourceType') return $x//TEST/text()");

		assertNotNull("quick search cannot be null", res);

		Collections.sort(res);
		final String[] ordered = (String[]) res.toArray(new String[] {});

		assertArrayEquals(new String[] { "123", "666" }, ordered);
	}

	/**
	 * run an xquery and use the resultset interface to get the results.
	 *
	 * @throws ISStoreException
	 *             shoudn't happen
	 * @throws ISLookUpException
	 *             shoudn't happen
	 * @throws ResultSetException
	 *             shoudn't happen
	 */
	@Test
	public void testResultSet() throws ISLookUpException, ISStoreException, ResultSetException {
		final W3CEndpointReference epr = lookupLocator.getService().searchProfile(
				"for $x in collection('/db/DRIVER/TestResources/TestResourceType') return $x");
		epr.writeTo(new StreamResult(System.out));
		final ResultSetService rset = serviceResolver.getService(ResultSetService.class, epr);

		assertEquals("check resultset size", 2, rset.getNumberOfElements(serviceResolver.getResourceIdentifier(epr)));
	}

	/**
	 * test the exception for inexistent profiles.
	 *
	 * @throws ISLookUpException expected
	 */
	@Test(expected = ISLookUpDocumentNotFoundException.class)
	public void testInexistentProfile() throws ISLookUpException {
		lookupLocator.getService().getResourceProfile("1234");
	}

	/**
	 * test the exception for inexistent profiles.
	 *
	 * @throws ISLookUpException expected
	 */
	@Test(expected = ISLookUpDocumentNotFoundException.class)
	public void testInexistentProfileByQuery() throws ISLookUpException {
		lookupLocator.getService().getResourceProfileByQuery("for $x in collection('/db/DRIVER/Nothing') return $x");
	}
}
