package eu.dnetlib.enabling.locators;

import java.util.Map;
import java.util.Set;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
import eu.dnetlib.enabling.locators.comparators.PreferLocalRunningInstanceComparator;
import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
import eu.dnetlib.enabling.tools.OpaqueResource;
import eu.dnetlib.enabling.tools.registration.ServiceNameResolver;
import eu.dnetlib.enabling.tools.registration.ServiceRegistrationManager;
import org.antlr.stringtemplate.StringTemplate;
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.context.ApplicationContext;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class DefaultUniqueServiceLocatorTest {

	/**
	 * Class under test.
	 */
	private DefaultUniqueServiceLocator locator;

	@Mock
	private ISLookUpService lookupService;
	@Mock
	private ResultSetService resultsetService;
	@Mock
	private ApplicationContext appContext;
	@Mock
	private ServiceNameResolver serviceNameResolver;
	@Mock
	private ServiceRegistrationManager resultSetRegistrator;
	@Mock
	private OpaqueResource opaqueResource;

	private static final String SERVICE_NAME = "ResultsetService";

	private static final String XQUERY = "for $x in collection('/db/DRIVER/ServiceResources/" + SERVICE_NAME + "ResourceType') return $x";

	@Before
	public void setUp() throws Exception {
		locator = new DefaultUniqueServiceLocator();
		locator.setApplicationContext(appContext);
		locator.setDefaultComparator(new PreferLocalRunningInstanceComparator());
		locator.setServiceNameResolver(serviceNameResolver);
		locator.setIsLookupService(lookupService);

		final Map<String, ServiceRegistrationManager> registratorBeans = Maps.newHashMap();
		registratorBeans.put("resultSetRegistrator", resultSetRegistrator);
		final Map<String, ResultSetService> serviceBeans = Maps.newHashMap();
		serviceBeans.put("resultSetService", resultsetService);

		final StringTemplate st1 = new StringTemplate(IOUtils.toString(getClass().getResourceAsStream("serviceProfile.xml.st")));
		st1.setAttribute("name", SERVICE_NAME);
		st1.setAttribute("id", "1111");
		final StringTemplate st2 = new StringTemplate(IOUtils.toString(getClass().getResourceAsStream("serviceProfile.xml.st")));
		st2.setAttribute("name", SERVICE_NAME);
		st2.setAttribute("id", "2222");
		final StringTemplate st3 = new StringTemplate(IOUtils.toString(getClass().getResourceAsStream("serviceProfile.xml.st")));
		st3.setAttribute("name", SERVICE_NAME);
		st3.setAttribute("id", "3333");

		when(serviceNameResolver.getName(ResultSetService.class)).thenReturn(SERVICE_NAME);
		when(lookupService.quickSearchProfile(XQUERY)).thenReturn(Lists.newArrayList(st1.toString(), st2.toString(), st3.toString()));
		when(lookupService.getResourceProfileByQuery(anyString())).thenReturn(st2.toString());
		//when(appContext.getBeansOfType(ServiceRegistrationManager.class)).thenReturn(registratorBeans);
		//when(appContext.getBeansOfType(ResultSetService.class)).thenReturn(serviceBeans);

		//when(resultSetRegistrator.getServiceProfile()).thenReturn(opaqueResource);
		//when(resultSetRegistrator.getService()).thenReturn(resultsetService);
		//when(opaqueResource.getResourceId()).thenReturn("2222");

	}

	@Test
	public void testGetServiceClassOfT_1() {
		assertEquals(lookupService, locator.getService(ISLookUpService.class));
	}

	@Test
	@Ignore
	public void testGetServiceClassOfT_2() throws ISLookUpException {
		assertEquals(resultsetService, locator.getService(ResultSetService.class, false));
		verify(lookupService, times(1)).quickSearchProfile(XQUERY);
	}

	@Test
	@Ignore
	public void testGetServiceClassOfTComparatorOfServiceRunningInstance() throws ISLookUpException {
		assertEquals(resultsetService, locator.getService(ResultSetService.class, new PreferLocalRunningInstanceComparator()));
		verify(lookupService, times(1)).quickSearchProfile(XQUERY);
	}

	@Test
	@Ignore
	public void testGetServiceClassOfTString() {
		assertEquals(resultsetService, locator.getService(ResultSetService.class, "rs-1234"));
	}

	@Test
	@Ignore
	public void testGetServiceClassOfTBoolean() throws ISLookUpException {
		assertEquals(resultsetService, locator.getService(ResultSetService.class, true));
		verify(lookupService, never()).quickSearchProfile(XQUERY);
	}

	@Test
	public void testGetServiceIdClassOfT() {
		assertEquals("1111", locator.getServiceId(ResultSetService.class));
	}

	@Test
	public void testGetServiceIdClassOfTComparatorOfServiceRunningInstance() {
		assertEquals("1111", locator.getServiceId(ResultSetService.class, new PreferLocalRunningInstanceComparator()));
	}

	@Test
	public void testGetServiceIdClassOfTString() {
		assertEquals("2222", locator.getServiceId(ResultSetService.class, "rs-1234"));
	}

	@Test
	@Ignore
	public void testGetAllServices() {
		final Set<ResultSetService> list = locator.getAllServices(ResultSetService.class);
		assertEquals(3, list.size());
		assertTrue(list.contains(resultsetService));
	}

	@Test
	public void testGetAllServiceIds() {
		final Set<String> list = locator.getAllServiceIds(ResultSetService.class);
		assertEquals(3, list.size());
		assertTrue(list.contains("1111"));
		assertTrue(list.contains("2222"));
		assertTrue(list.contains("3333"));
	}

}
