package eu.dnetlib.enabling.is.registry;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import javax.xml.xpath.XPathExpressionException;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import eu.dnetlib.enabling.is.registry.rmi.ISRegistryException;
import eu.dnetlib.enabling.is.registry.rmi.ISRegistryService;
import eu.dnetlib.enabling.is.registry.schema.ValidationException;
import eu.dnetlib.enabling.is.registry.validation.ProfileValidationStrategy;
import eu.dnetlib.enabling.is.registry.validation.RegistrationPhase;
import eu.dnetlib.enabling.tools.OpaqueResource;

/**
 * test compatibility pending resource manager implementation.
 * 
 * @author marko
 * 
 */
@RunWith(MockitoJUnitRunner.class)
public class CompatPendingResourceManagerImplTest {

	/**
	 * instance under test.
	 */
	private transient CompatPendingResourceManagerImpl pendingManager;

	/**
	 * registry service mock.
	 */
	@Mock
	private transient ISRegistryService registryService;

	/**
	 * resource mock.
	 */
	@Mock
	private transient OpaqueResource resource;
	/**
	 * used to validate resources w.r.t. a set of defined properties.
	 */
	@Mock
	private ProfileValidationStrategy profileValidationStrategy;

	/**
	 * prepare instance for testing.
	 */
	@Before
	public void setUp() {
		pendingManager = new CompatPendingResourceManagerImpl();
		pendingManager.setIsRegistry(registryService);
		pendingManager.setResourceKindResolver(new ApplicationProfileResourceKindResolver());
		pendingManager.setProfileValidationStrategy(profileValidationStrategy);
	}

	/**
	 * test that the application profile can be queried correctly.
	 * 
	 * @throws XPathExpressionException
	 *             shouldn't happen
	 */
	@Test
	public void testGetPendingKindForType() throws XPathExpressionException {
		assertEquals("check pending", "PendingRepositoryResources", pendingManager.getPendingKindForType("RepositoryServiceResourceType"));
		assertEquals("check pending", "PendingDSResources", pendingManager.getPendingKindForType("UserDSResourceType"));
	}

	/**
	 * check that unexistent types throw an exception.
	 * 
	 * @throws XPathExpressionException
	 *             shouldn't happen
	 */
	@Test(expected = IllegalStateException.class)
	public void testGetPendingKindForNoSuchType() throws XPathExpressionException {
		pendingManager.getPendingKindForType("NoSuchType");
	}

	/**
	 * test that the application profile can be queried correctly.
	 * 
	 * @throws XPathExpressionException
	 *             shouldn't happen
	 */
	@Test
	public void testGetNormalKindForType() throws XPathExpressionException {
		assertEquals("check kind", "RepositoryServiceResources", pendingManager.getNormalKindForType("RepositoryServiceResourceType"));
		assertEquals("check kind", "UserDSResources", pendingManager.getNormalKindForType("UserDSResourceType"));
		assertNull("check unexisting type", pendingManager.getNormalKindForType("NoSuchType"));
	}

	/**
	 * test that the resource is correctly moved from the pending collection to the new collection.
	 * 
	 * @throws ISRegistryException
	 *             shoudn't happen
	 * @throws ValidationException
	 */
	@Test
	public void testSetValid() throws ISRegistryException, ValidationException {
		final String profId = "123";
		when(resource.asString()).thenReturn("");
		when(resource.getResourceId()).thenReturn(profId);
		//when(profileValidationStrategy.accept(any(OpaqueResource.class), eq(RegistrationPhase.Register))).thenReturn(true);

		pendingManager.setValid(resource);

		verify(registryService).deleteProfile(profId);
		verify(registryService).registerProfile(anyString());

		assertNotNull("dummy", registryService);
	}

	/**
	 * test that the resource is correctly moved from the current collection to the correct pending collection.
	 * 
	 * @throws ISRegistryException
	 *             shoudn't happen
	 */
	@Test
	public void testSetPending() throws ISRegistryException {
		final String profId = "321";
		when(resource.asString()).thenReturn("");
		when(resource.getResourceId()).thenReturn(profId);
		when(resource.getResourceType()).thenReturn("RepositoryServiceResourceType");

		pendingManager.setPending(resource);

		verify(registryService).deleteProfile(profId);
		verify(registryService).registerProfile(anyString());

		assertNotNull("dummy", registryService);
	}

}
