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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Collection;

import org.junit.Before;
import org.junit.Test;

import eu.dnetlib.enabling.is.sn.SubscriptionRequest;
import eu.dnetlib.test.utils.EPRTestUtil;

/**
 * Common tests for resource state subscription registry tests.
 * 
 * @author marko
 * 
 */
public abstract class AbstractResourceStateSubscriptionRegistryTest {

	/**
	 * star.
	 */
	private static final String STAR = "*";

	/**
	 * create topic prefix.
	 */
	private static final String CREATE = "CREATE";

	/**
	 * test resource type.
	 */
	private static final String SOME_TYPE = "someType";

	/**
	 * test other resource type.
	 */
	private static final String SOME_OTHER_TYPE = "someOtherType";

	/**
	 * test resource id.
	 */
	private static final String SOME_ID = "sub123";

	/**
	 * instance under test.
	 */
	private ResourceStateSubscriptionRegistry registry;

	/**
	 * test subscritpion request.
	 */
	private transient SubscriptionRequest sub;

	/**
	 * setup registry. subclasses should set the dao.
	 */
	@Before
	public void setUpRegistry() {
		registry = new ResourceStateSubscriptionRegistry();
		setUpDao();

		sub = new SubscriptionRequest(SOME_ID, EPRTestUtil.getTestEpr(), "CREATE/*/*", 0);
	}

	/**
	 * test subscription registration.
	 */
	@Test
	public void testRegisterSubscription() {
		registry.registerSubscription(sub);

		final Collection<ResourceStateSubscription> res = registry.listMatchingSubscriptions(CREATE, STAR, STAR);
		for (ResourceStateSubscription r : res)
			assertEquals("check add subscription", SOME_ID, r.getSubscriptionId());

		assertEquals("check that is really added", 1, res.size());
	}
	
	/**
	 * test match.
	 */
	@Test
	public void testMatch() {
		registry.registerSubscription(sub);
		
		ResourceStateSubscription re1 = null; // NOPMD
		ResourceStateSubscription re2 = null; // NOPMD
		
		final Collection<ResourceStateSubscription> res = registry.listMatchingSubscriptions(CREATE, SOME_TYPE, STAR);
		for (ResourceStateSubscription r : res) {
			re1 = r; // NOPMD
			assertEquals("check match subscription", SOME_ID, r.getSubscriptionId());
		}

		assertEquals("check that only one matched", 1, res.size());
		
		final Collection<ResourceStateSubscription> res2 = registry.listMatchingSubscriptions(CREATE, SOME_OTHER_TYPE, STAR);
		for (ResourceStateSubscription r : res2) {
			re2 = r; // NOPMD
			assertEquals("check match subscription", SOME_ID, r.getSubscriptionId());
		}

		assertEquals("check that only one matched", 1, res2.size());
		assertEquals("check that the same subscription is returned", re1, re2);
	}

	/**
	 * multiple subscriptions should be registered only once.
	 */
	@Test
	public void testMultiple() {
		final String subId = registry.registerSubscription(sub);
		final String subId2 = registry.registerSubscription(sub);
		
		assertEquals("avoid duplicates", subId, subId2); 
	}
	
	/**
	 * test unsubscribe.
	 */
	@Test
	public void testUnsubscribe() {
		final String subId = registry.registerSubscription(sub);
		final boolean res = registry.unsubscribe(subId);
		
		assertTrue("unsubscribed", res);
		
		
		final boolean res2 = registry.unsubscribe(subId);
		
		assertFalse("not unsubscribed", res2);
	}
	
	/**
	 * subclasses should implement this with a specific instance of the dao.
	 */
	protected abstract void setUpDao();

	public ResourceStateSubscriptionRegistry getRegistry() {
		return registry;
	}

	public void setRegistry(final ResourceStateSubscriptionRegistry registry) {
		this.registry = registry;
	}

}
