package eu.dnetlib.functionality.index.solr;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Required;

import eu.dnetlib.common.interfaces.nh.IBlackboardMessage.Action;
import eu.dnetlib.data.index.IndexServiceException;
import eu.dnetlib.enabling.tools.blackboard.AbstractBlackboardNotificationHandler;
import eu.dnetlib.enabling.tools.blackboard.BlackboardJob;
import eu.dnetlib.enabling.tools.blackboard.BlackboardServerHandler;
import eu.dnetlib.enabling.tools.blackboard.NotificationHandler;
import eu.dnetlib.functionality.index.solr.worker.FeedExecutor;

/**
 * 
 *
 * @author claudio
 *
 */
public class SolrIndexNotificationHandler 
	extends AbstractBlackboardNotificationHandler<BlackboardServerHandler> 
	implements NotificationHandler {

	/**
	 * logger.
	 */
	private static final Log log = LogFactory.getLog(SolrIndexNotificationHandler.class); 

	/**
	 * index service.
	 */
	private SolrIndexServiceImpl indexService;
	
	/**
	 * Index feeding executor.
	 */
	private FeedExecutor feedExecutor;
	
	/**
	 * Executor that performs index creation.
	 */
	private ExecutorService createExecutor = Executors.newSingleThreadExecutor();
	
	/**
	 * Executor that performs index record delete.
	 */
	private ExecutorService deleteExecutor = Executors.newSingleThreadExecutor();

	@Override
	protected void processJob(BlackboardJob job) {
		log.info("processing solr index job: " + job.getAction());
		
		final Action action = Action.valueOf(job.getAction());
		try {
			switch (action) {
			
			case CREATE: 
				performCreateIndex(job);
				break;
				
			case FEED:
				feedExecutor.startFeeding(job);
				break;

			case DELETE:
				performDelete(job);
				break;
				
			case IDENTIFY:
				job.getParameters().put("service_id", indexService.identify());
				break;
			
			default:
				job.setError("unsupported Action: " + action.name());
				log.warn("unsupported message action: " + action.name());
				throw new IllegalArgumentException("unsupported message action: " + action.name());				
			}

		} catch (Throwable e) {
			log.error(e.getMessage(), e);
			getBlackboardHandler().failed(job, e);
		}
	}

	private void performCreateIndex(final BlackboardJob job) throws IndexServiceException {
		
		getBlackboardHandler().ongoing(job);
		log.info("CREATE job set to ONGOING");
		
		createExecutor.execute(new Runnable() {
			
			@Override
			public void run() {
				try {
					final String profileId = indexService.createIndex(job);
					job.getParameters().put("id", profileId);
					
					getBlackboardHandler().done(job);
					log.info("CREATE job set to DONE");
				} catch (Throwable e) {
					log.error("CREATE job set to FAILED ", e);
					getBlackboardHandler().failed(job, e);
				} 
			}
		});
	}
	
	private void performDelete(final BlackboardJob job) {
		deleteExecutor.execute(new Runnable() {
			
			@Override
			public void run() {
				try {
					indexService.deleteIndex(job);
					
					getBlackboardHandler().done(job);
					log.info("DELETE job set to DONE");
				} catch (Throwable e) {
					log.error("DELETE job set to FAILED ", e);
					getBlackboardHandler().failed(job, e);
				}
			}
		});
		
		getBlackboardHandler().ongoing(job);
		log.info("DELETE job set to ONGOING");
		
	}
	
	///////////////////// setters and getters

	@Required
	public void setIndexService(SolrIndexServiceImpl indexService) {
		this.indexService = indexService;
	}
	
	public SolrIndexServiceImpl getIndexService() {
		return indexService;
	}

	public FeedExecutor getFeedExecutor() {
		return feedExecutor;
	}

	@Required
	public void setFeedExecutor(FeedExecutor feedExecutor) {
		this.feedExecutor = feedExecutor;
	}

}