package eu.dnetlib.data.collective.manager.scheduling;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import java.util.LinkedList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnit44Runner;

import eu.dnetlib.common.ws.subscription.AbstractSubscription;
import eu.dnetlib.data.collective.manager.nh.AbstractServiceNotificationHandler;
import eu.dnetlib.data.collective.manager.nh.INotificationConsumer;
import eu.dnetlib.data.collective.manager.profile.AbstractInstance;
import eu.dnetlib.data.collective.manager.scheduling.profile.EventScheduling;
import eu.dnetlib.data.collective.manager.scheduling.profile.SchedulingConfiguration;

@RunWith(MockitoJUnit44Runner.class)
public class EventRegistryTest {

	public transient EventRegistry<AbstractInstance> eventRegistry;
	public transient String storePath = "/tmp/";
	
	@Mock
	private transient AbstractInstance instance;
	
	@Mock
	private transient AbstractSubscription subscriber;
	
	private transient AbstractServiceNotificationHandler<INotificationConsumer> notificationHandler = new AbstractServiceNotificationHandler<INotificationConsumer>();

	@Mock
	private transient SchedulingConfiguration schedulingConfig;
	
	@Mock
	private transient EventScheduling eventScheduling;
	
	private transient String topic = "topic-xyz";
	private transient String subscriptionId = "123";
	private transient List<String> dataSourceIds = new LinkedList<String>();
	private transient String dataSourceId = "ds-456";
	private transient String instanceId = "instance-789";
	
	@Before
	public void setUp(){
		eventRegistry = new EventRegistry<AbstractInstance>();
		eventRegistry.setStorePath(storePath);
		eventRegistry.setEventNotificationHandler(notificationHandler);
		eventRegistry.setSubscriber(subscriber);
		eventRegistry.init();
		
		dataSourceIds.add(dataSourceId);
		
		when(instance.getScheduling()).thenReturn(schedulingConfig);
		when(instance.getScheduling().getEventScheduling()).thenReturn(eventScheduling);
		when(instance.getScheduling().isEventSchedulingConfigured()).thenReturn(true);
		when(instance.getScheduling().getEventScheduling().getTopic()).thenReturn(topic);
		when(instance.getDataSourceIds()).thenReturn(dataSourceIds);
		when(subscriber.subscribeTopic(topic)).thenReturn(subscriptionId);
		when(instance.getResourceId()).thenReturn(instanceId);
	}
	
	@Test
	public void AddAndRemoveEvent(){
		// register instance for an event -> only one event per instance
		assertTrue(eventRegistry.addInstance(instance));
		assertEquals(1, notificationHandler.getTopicPrefixes().size());
		assertEquals(instanceId, eventRegistry.getInstanceId(dataSourceId));
		assertTrue(eventRegistry.isRegisteredEvent(dataSourceId));

		// now unregister instance
		when(instance.getScheduling().getEventScheduling()).thenReturn(null);
		when(instance.getScheduling().isEventSchedulingConfigured()).thenReturn(false);
		assertTrue(eventRegistry.updateInstance(instance));
		assertNotSame(instanceId, eventRegistry.getInstanceId(dataSourceId));
		assertTrue(notificationHandler.getTopicPrefixes().isEmpty());
	}
}
