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

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnit44Runner;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;

import eu.dnetlib.common.interfaces.nh.IBlackboardMessage.Action;
import eu.dnetlib.common.profile.Resource;
import eu.dnetlib.data.collective.manager.nh.AbstractServiceBlackboardNotificationHandler;
import eu.dnetlib.data.collective.manager.scheduling.mock.InstanceMock;
import eu.dnetlib.data.collective.manager.scheduling.mock.InstanceSchedulingMock;
import eu.dnetlib.data.collective.manager.scheduling.mock.WorkerServiceManagerMock;
import eu.dnetlib.data.collective.manager.scheduling.profile.CronScheduling;
import eu.dnetlib.data.collective.manager.scheduling.profile.SchedulingConfiguration;
import eu.dnetlib.data.collective.manager.utils.ServiceRegistry;
import eu.dnetlib.data.collective.worker.mock.WorkerServiceMock;
import eu.dnetlib.enabling.tools.blackboard.BlackboardClientHandlerImpl;
import eu.dnetlib.enabling.tools.blackboard.BlackboardJob;

@RunWith(MockitoJUnit44Runner.class)
public class SchedulerTest {

	private static final Log log = LogFactory.getLog(SchedulerTest.class);
	private static final String workerServiceId = "anyId";
	private static final String resourceId = "anyResourceId";
	
	@Mock
	private transient Resource resource;
	
	@Mock
	private transient WorkerServiceManagerMock workerServiceManagerMock;
	
	@Mock
	private transient BlackboardClientHandlerImpl blackboardClientHandler;
	
	@Mock
	private transient AbstractServiceBlackboardNotificationHandler workerServiceBlackboardNotificationHandler;
	@Mock
	private transient BlackboardJob blackboardJob;
	@Mock
	private transient ServiceRegistry<WorkerServiceMock> serviceRegistry;
	private transient WorkerServiceMock workerService = new WorkerServiceMock();
	
	@Mock
	private transient InstanceMock instanceMock;
	@Mock
	private transient SchedulingConfiguration schedConf;
	@Mock
	private transient CronScheduling cronSched;

	private transient Scheduler scheduler;
	
	private transient InstanceSchedulingMock instanceSchedulingMock;
	
	private String cronexpression = "0/15 * * ? * *";

	@Before
	public void setUp() throws SchedulerException{
		
		scheduler = new StdSchedulerFactory().getScheduler();
		scheduler.start();
		
		when(instanceMock.getResourceId()).thenReturn(resourceId);
		when(instanceMock.getDefaultBlackboardMessageAction()).thenReturn(Action.MANAGE);
		when(instanceMock.getScheduling()).thenReturn(schedConf); 
		when(schedConf.getCronScheduling()).thenReturn(cronSched);
		when(cronSched.getWhen()).thenReturn(cronexpression );
		when(schedConf.isCronSchedulingConfigured()).thenReturn(true);

		when(serviceRegistry.add(workerServiceId, "someUri")).thenReturn(true);
		when(serviceRegistry.size()).thenReturn(1);
		when(serviceRegistry.getService(workerServiceId)).thenReturn(workerService);
		when(serviceRegistry.next()).thenReturn(workerServiceId);
		workerServiceManagerMock.setServiceRegistry(serviceRegistry);
		when(serviceRegistry.getService(workerServiceId)).thenReturn(workerService);
		
		when(blackboardClientHandler.newJob(workerServiceId)).thenReturn(blackboardJob);

		instanceSchedulingMock = new InstanceSchedulingMock();
		instanceSchedulingMock.setJobBeanClazz(AbstractServiceJob.class);		
		instanceSchedulingMock.setWorkerServiceManager(workerServiceManagerMock);
		instanceSchedulingMock.setBbClientHandler(blackboardClientHandler);
		instanceSchedulingMock.setBbJobRegistry(workerServiceBlackboardNotificationHandler);
		instanceSchedulingMock.setScheduler(scheduler);
//		instanceSchedulingMock.init();
		when(workerServiceManagerMock.getServiceRegistry()).thenReturn(serviceRegistry);

	}
	
	@Test
	public void testScheduling(){
		assertEquals(1, serviceRegistry.size());
		
		workerServiceManagerMock.addResource(resource);
				
		try {
			instanceSchedulingMock.addInstance(instanceMock);
			assertNotNull(instanceMock.getDefaultBlackboardMessageAction());
			assertTrue(instanceSchedulingMock.isSchedulerStarted());
			assertEquals(1, instanceSchedulingMock.getNumberOfJobs());
			log.debug("next fire: " + instanceSchedulingMock.getNextFireTime(resourceId));
            Thread.sleep(20000);
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}
