package eu.dnetlib.enabling.tools;

import static org.junit.Assert.assertEquals;

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.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
import eu.dnetlib.enabling.tools.registration.DriverTesterService;
import eu.dnetlib.enabling.tools.registration.ServiceRegistrationManagerImpl;
import eu.dnetlib.test.AbstractIntegrationContainerTest;
import eu.dnetlib.test.SpringContextSharer;

/**
 * test dynamic service locators.
 * 
 * @author marko
 * 
 */
@RunWith(SpringJUnit4ClassRunner.class)
public class DynamicServiceLocatorTest extends AbstractIntegrationContainerTest {

	/**
	 * wait = time step * TIMES.
	 */
	private static final int TIMES = 600;
	
	/**
	 * wait timestep.
	 */
	private static final int TIMESTEP = 100;
	
	/**
	 * logger.
	 */
	private static final Log log = LogFactory.getLog(DynamicServiceLocatorTest.class); // NOPMD by marko on 11/24/08 5:02 PM

	/**
	 * dynamic lookUp service locator.
	 */
	private transient ServiceLocator<DriverTesterService> testerLocator;

	/**
	 * dynamic lookUp service locator.
	 */
	private transient ServiceLocator<ISLookUpService> lookUpLocator;
	
	/**
	 * dynamic lookUp service locator with static fallback.
	 */
	private transient ServiceLocator<ISLookUpService> fallbackLookUpLocator;

	/**
	 * static lookUp service locator, for comparing with fallback. 
	 */
	private transient ServiceLocator<ISLookUpService> staticLookUpLocator;

	/**
	 * registration manager, used to check when the service profile subscription is finished.
	 */
	private transient ServiceRegistrationManagerImpl manager;
	
	/**
	 * common setup.
	 */
	@SuppressWarnings("unchecked")
	@Before
	public void setUp() {
		log.debug("setting up a child context");

		final ApplicationContext context = new ClassPathXmlApplicationContext(
				new String[] { "eu/dnetlib/enabling/tools/DynamicServiceLocatorTest-server-context.xml" }, SpringContextSharer.getGlobalContext());
		manager = (ServiceRegistrationManagerImpl) context.getBean("dynamicServiceRegistrationManager", ServiceRegistrationManagerImpl.class);
		
		testerLocator = (ServiceLocator<DriverTesterService>) context.getBean("dynamicTesterServiceLocator");
		lookUpLocator = (ServiceLocator<ISLookUpService>) context.getBean("dynamicLookUpServiceLocator");	
		fallbackLookUpLocator = (ServiceLocator<ISLookUpService>) context.getBean("fallbackLookUpServiceLocator");	
		staticLookUpLocator = (ServiceLocator<ISLookUpService>) context.getBean("lookupLocator");	
	}

	/**
	 * test dynamic lookUp invocation.
	 * 
	 * @throws InterruptedException could happen.
	 */
	@Test
	public void testDynamicTesterService() throws InterruptedException {
		for (int i = 0; i < TIMES; i++) {
			Thread.sleep(TIMESTEP);
			if (manager.getState() == ServiceRegistrationManagerImpl.State.REGISTERED)
				break;
		}
		
		assertEquals("check real service", "DriverTesterService", testerLocator.getService().identify());
	}
	
	/**
	 * The lookup service shouldn't be found, not only because we inhibit default service registration at during integration
	 * tests, but also because the lookup service would be registered using a compatibility rule for the service name, which
	 * is not set up in this test.
	 * 
	 * @throws InterruptedException
	 */
	@Test(expected = IllegalStateException.class)
	public void testDynamicLookUpService() {
		lookUpLocator.getService();
	}
	
	/**
	 * test fallback. 
	 */
	@Test
	public void testFallbackLookUpService() {
		assertEquals(staticLookUpLocator.getService(), fallbackLookUpLocator.getService());
	}
}
