package eu.dnetlib.openaire.common;

import java.util.List;
import java.util.concurrent.*;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

@Component
public class OperationManager {

	private static final Log log = LogFactory.getLog(OperationManager.class);

	private static final long SLEEP_TIME = 1000;

	private static final int Q_SIZE = 100;

	private static final int POOL_SIZE = 5;

	private final BlockingQueue<Runnable> ops = new ArrayBlockingQueue<>(Q_SIZE);

	private ExecutorService executor;

	@PostConstruct
	public void init() {
		executor = getExecutor();
	}

	public int dropAll() {
		final List<Runnable> lostOperations = executor.shutdownNow();
		log.warn(String.format("discarding %s operations", lostOperations.size()));
		executor = getExecutor();
		return lostOperations.size();
	}

	public int getOpSize() {
		return ops.size();
	}

	public void addOperation(final Runnable op) {
		executor.execute(op);
	}

	@PreDestroy
	public void tearDown() throws InterruptedException {
		executor.shutdown();
		final boolean done = executor.awaitTermination(SLEEP_TIME, TimeUnit.MILLISECONDS);
		log.debug(String.format("All operations were completed so far? %s", done));
	}

	// HELPERS

	private ThreadPoolExecutor getExecutor() {
		return new ThreadPoolExecutor(POOL_SIZE, POOL_SIZE,0L, TimeUnit.MILLISECONDS, ops);
	}

}
