package eu.dnetlib.enabling.is.sn.resourcestate;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; // NOPMD
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.verify; // NOPMD

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 eu.dnetlib.enabling.is.sn.SubscriptionRequest;
import eu.dnetlib.enabling.is.sn.rmi.SubscriptionRequestRejectedException;

/**
 * test ResourceStateSubscriptionRegistryTest.
 *
 * @author marko
 *
 */
@RunWith(MockitoJUnitRunner.class)
public class ResourceStateSubscriptionRegistryTest {

	/**
	 * matches.
	 * 
	 * @author marko
	 *
	 */
	public static class MatchSubscription implements ArgumentMatcher<ResourceStateSubscription> {

		/**
		 * prefix.
		 */
		private final transient String prefix;

		/**
		 * type.
		 */
		private final transient String type;

		/**
		 * resource id.
		 */
		private final transient String resId;

		/**
		 * create a new match subscription checker for a given prefix and a given type.
		 * 
		 * @param prefix
		 *            prefix
		 * @param type
		 *            type
		 * @param resId
		 *            resource id
		 */
		MatchSubscription(final String prefix, final String type, final String resId) {
			super();
			this.prefix = prefix;
			this.type = type;
			this.resId = resId;
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.mockito.ArgumentMatcher#matches(java.lang.Object)
		 */
		@Override
		public boolean matches(final ResourceStateSubscription sub) {
			return sub.getPrefix().equals(this.prefix) && sub.getType().equals(this.type) && sub.getResourceId().equals(this.resId);
		}

	}

	/**
	 * object under test.
	 */
	private transient ResourceStateSubscriptionRegistry registry;

	/**
	 * DAO mock.
	 */
	@Mock
	private transient ResourceStateSubscriptionDAO subscriptionDao;

	/**
	 * subscription request.
	 */
	private transient SubscriptionRequest sub;

	/**
	 * common setup.
	 */
	@Before
	public void setUp() {
		registry = new ResourceStateSubscriptionRegistry();
		registry.setSubscriptionDao(subscriptionDao);

		final SubscriptionRequestFilter filter = new SubscriptionRequestFilter();
		filter.setActive(true);
		registry.setSubscriptionRequestFilter(filter);

		sub = new SubscriptionRequest();
	}

	/**
	 * test registration.
	 * 
	 * @throws SubscriptionRequestRejectedException
	 */
	@Test
	public void testRegisterSubscription() throws SubscriptionRequestRejectedException {
		sub.setTopicExpression("CREATE/MyResourceType/123/some/path");
		registry.registerSubscription(sub);
		verify(subscriptionDao).addSubscription(argThat(new MatchSubscription("CREATE", "MyResourceType", "123")));

		assertNotNull("dummy", subscriptionDao);
	}

	/**
	 * test registration.
	 * 
	 * @throws SubscriptionRequestRejectedException
	 */
	@Test(expected = SubscriptionRequestRejectedException.class)
	public void testRegisterSubscriptionReject1() throws SubscriptionRequestRejectedException {

		sub.setTopicExpression("UPDATE/OtherResourceType");
		registry.registerSubscription(sub);
		verify(subscriptionDao).addSubscription(argThat(new MatchSubscription("UPDATE", "OtherResourceType", "*")));

		assertNotNull("dummy", subscriptionDao);
	}

	/**
	 * test registration.
	 * 
	 * @throws SubscriptionRequestRejectedException
	 */
	@Test(expected = SubscriptionRequestRejectedException.class)
	public void testRegisterSubscriptionReject2() throws SubscriptionRequestRejectedException {

		sub.setTopicExpression("DELETE/*");
		registry.registerSubscription(sub);
		verify(subscriptionDao).addSubscription(argThat(new MatchSubscription("DELETE", "*", "*")));

		assertNotNull("dummy", subscriptionDao);
	}

	/**
	 * test registration.
	 * 
	 * @throws SubscriptionRequestRejectedException
	 */
	@Test(expected = SubscriptionRequestRejectedException.class)
	public void testRegisterSubscriptionReject3() throws SubscriptionRequestRejectedException {

		sub.setTopicExpression("CREATE");
		registry.registerSubscription(sub);
		verify(subscriptionDao).addSubscription(argThat(new MatchSubscription("CREATE", "*", "*")));

		assertNotNull("dummy", subscriptionDao);
	}

	/**
	 * test match id.
	 */
	@Test
	public void testMatchId() {
		assertEquals("check pure id", "1234123", registry.matchId("1234123").getPrefix());
		assertEquals("check with suffix", "1234123", registry.matchId("1234123/blabla/blabla").getPrefix());
		assertEquals("check suffix", "/blabla/blabla", registry.matchId("1234123/blabla/blabla").getRest());
	}

}
