package eu.dnetlib.data.download;

import java.util.List;
import javax.annotation.Resource;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import eu.dnetlib.data.download.rmi.DownloadServiceActions;
import eu.dnetlib.data.download.rmi.DownloadServiceException;
import eu.dnetlib.data.download.rmi.DownloadServiceFeeder;
import eu.dnetlib.enabling.tools.blackboard.BlackboardJob;
import eu.dnetlib.enabling.tools.blackboard.BlackboardServerAction;
import eu.dnetlib.enabling.tools.blackboard.BlackboardServerHandler;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class DownloadAction implements BlackboardServerAction<DownloadServiceActions> {

	/** The Constant log. */
	private static final Log log = LogFactory.getLog(DownloadAction.class);
	private static String DEFAULT_NUMBER_OF_THREAD = "5";
	private static int DEFAULT_TIMEOUT_MS = 5000;
	@Resource
	private DownloadServiceFeeder downloadServiceFeeder;

	@Override
	public void execute(final BlackboardServerHandler handler, final BlackboardJob job) throws Exception {
		int connectTimeoutMs = DEFAULT_TIMEOUT_MS;
		int readTimeoutMs = DEFAULT_TIMEOUT_MS;
		int sleepTimeMs = 0;
		try {
			String epr = job.getParameters().get("epr");
			String plugin = job.getParameters().get("plugin");
			String objectStoreID = job.getParameters().get("objectStoreID");
			String protocol = job.getParameters().get("protocol");
			String mimeType = job.getParameters().get("mimeType");
			String numberOfThreads = job.getParameters().get("numberOfThreads");
			String basePath = job.getParameters().get("basePath");
			String regularExpression = job.getParameters().get("regularExpressions");
			String connectTimeoutMsStr = job.getParameters().get("connectTimeoutMs");
			String readTimeoutMsStr = job.getParameters().get("readTimeoutMs");
			String sleepTimeMsStr = job.getParameters().get("sleepTimeMs");
			log.debug("regular Expression: " + regularExpression);

			List<String> expressions = null;

			if (!StringUtils.isBlank(regularExpression)) {
				expressions = parseRegexList(regularExpression);
			}

			if (StringUtils.isBlank(numberOfThreads)) {
				log.warn("Cannot find numberOfThread, using default value " + DEFAULT_NUMBER_OF_THREAD);
				numberOfThreads = DEFAULT_NUMBER_OF_THREAD;
			}

			if (StringUtils.isNotBlank(connectTimeoutMsStr)) connectTimeoutMs = Integer.parseInt(connectTimeoutMsStr);
			if (StringUtils.isNotBlank(readTimeoutMsStr)) readTimeoutMs = Integer.parseInt(readTimeoutMsStr);
			if (StringUtils.isNotBlank(sleepTimeMsStr)) sleepTimeMs = Integer.parseInt(sleepTimeMsStr);

			log.info(String.format("downloading using plugin %s , protocol : %s into ObjectStore id %s  ", plugin, protocol, objectStoreID));
			handler.ongoing(job);
			DownloadReportMap response = downloadServiceFeeder.download(epr, plugin, objectStoreID, protocol, mimeType, Integer.parseInt(numberOfThreads),
					basePath, expressions, connectTimeoutMs, readTimeoutMs, sleepTimeMs);
			if (response.getStatus()) {
				log.info(String.format("Completed Download, plugin: %s, protocol: %s, objectStoreID: %s", plugin, protocol, objectStoreID));
				job.getParameters().put("total", "" + response.getTotalDownloaded());
				job.getParameters().put("report", Base64.encodeBase64String(response.toString().getBytes()));
				handler.done(job);
			} else {
				log.error("download response is false" + response);

				handler.failed(job, new DownloadServiceException(
						"oops! something bad happen to our download hamsters, downloaded so far: " + response.getTotalDownloaded()));
			}
		} catch (Exception e) {
			log.error("An error occur while starting download", e);
			handler.failed(job, new DownloadServiceException(e));
		}
	}

	private List<String> parseRegexList(final String regularExpression) {
		log.info("parsing regex list: " + regularExpression);
		return new Gson().fromJson(regularExpression, new TypeToken<List<String>>() {}.getType());
	}

}
