package eu.dnetlib.msro.workflows.nodes.download;

import java.util.Map;

import com.googlecode.sarasvati.Engine;
import com.googlecode.sarasvati.NodeToken;
import com.googlecode.sarasvati.env.Env;
import eu.dnetlib.data.download.rmi.DownloadService;
import eu.dnetlib.enabling.tools.blackboard.BlackboardJob;
import eu.dnetlib.msro.workflows.nodes.BlackboardJobNode;
import eu.dnetlib.msro.workflows.nodes.ProgressJobNode;
import eu.dnetlib.msro.workflows.nodes.blackboard.BlackboardWorkflowJobListener;
import eu.dnetlib.msro.workflows.resultset.ProcessCountingResultSetFactory;
import eu.dnetlib.msro.workflows.util.ProgressProvider;
import eu.dnetlib.msro.workflows.util.ResultsetProgressProvider;
import eu.dnetlib.msro.workflows.util.WorkflowsConstants;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;

// TODO: Auto-generated Javadoc
/**
 * The Class DownloadFromMetadata is a job node that send a blackboard message to the Download service to start to download file from url
 * retrieved by Metadata .
 */
public class DownloadFromMetadataJobNode extends BlackboardJobNode implements ProgressJobNode {

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

	protected String regularExpression;
	/** The inputepr param. */
	private String inputeprParam;
	/** The obejct store id. */
	private String objectStoreID;
	/** The plugin. */
	private String plugin;
	/** The protocol. */
	private String protocol;
	/** The mime type. */
	private String mimeType;
	private int numberOfThreads = -1;
	private int connectTimeoutMs = -1;
	private int readTimeoutMs = -1;

	private int sleepTimeMs = 0;
	/** The process counting result set factory. */
	@Autowired
	private ProcessCountingResultSetFactory processCountingResultSetFactory;

	/** The progress provider. */
	private ResultsetProgressProvider progressProvider;

	/*
	 * (non-Javadoc)
	 *
	 * @see eu.dnetlib.msro.workflows.nodes.BlackboardJobNode#obtainServiceId(com.googlecode.sarasvati.NodeToken)
	 */
	@Override
	protected String obtainServiceId(final NodeToken token) {
		return getServiceLocator().getServiceId(DownloadService.class);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see eu.dnetlib.msro.workflows.nodes.BlackboardJobNode#prepareJob(eu.dnetlib.enabling.tools.blackboard.BlackboardJob,
	 * com.googlecode.sarasvati.NodeToken)
	 */
	@Override
	protected void prepareJob(final BlackboardJob job, final NodeToken token) throws Exception {
		job.setAction("DOWNLOAD");
		final String eprS = token.getEnv().getAttribute(getInputeprParam());
		this.progressProvider = processCountingResultSetFactory.createProgressProvider(token.getProcess(), eprS);
		job.getParameters().put("epr", progressProvider.getEpr().toString());
		job.getParameters().put("protocol", getProtocol());
		job.getParameters().put("plugin", getPlugin());
		job.getParameters().put("mimeType", getMimeType());
		job.getParameters().put("objectStoreID", getObjectStoreID());
		if (getNumberOfThreads() > 0) {
			job.getParameters().put("numberOfThreads", "" + getNumberOfThreads());
		}
		if (getConnectTimeoutMs() > 0) {
			job.getParameters().put("connectTimeoutMs", "" + getConnectTimeoutMs());
		}
		if (getReadTimeoutMs() > 0) {
			job.getParameters().put("readTimeoutMs", "" + getReadTimeoutMs());
		}
		if (getSleepTimeMs() > 0) {
			job.getParameters().put("sleepTimeMs", "" + getSleepTimeMs());
		}
		if (!StringUtils.isEmpty(getRegularExpression())){
			job.getParameters().put("regularExpressions", getRegularExpression());
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see eu.dnetlib.msro.workflows.nodes.BlackboardJobNode#generateBlackboardListener(com.googlecode.sarasvati.Engine,
	 * com.googlecode.sarasvati.NodeToken)
	 */
	@Override
	protected BlackboardWorkflowJobListener generateBlackboardListener(final Engine engine, final NodeToken token) {
		return new BlackboardWorkflowJobListener(engine, token) {

			@Override
			protected void populateEnv(final Env env, final Map<String, String> responseParams) {
				env.setAttribute(WorkflowsConstants.MAIN_LOG_PREFIX + "total", responseParams.get("total"));

				final String base64 = responseParams.get("report");
				if (StringUtils.isNotBlank(base64) && Base64.isBase64(base64.getBytes())) {
					final String report = new String(Base64.decodeBase64(base64.getBytes()));
					log.info("found download report");
					log.debug(report);
					env.setAttribute(WorkflowsConstants.MAIN_LOG_PREFIX + "report", report);
				} else {
					log.warn("unable to find or decode download report");
				}
			}
		};
	}

	/**
	 * Gets the inputepr param.
	 *
	 * @return the inputeprParam
	 */
	public String getInputeprParam() {
		return inputeprParam;
	}

	/**
	 * Sets the inputepr param.
	 *
	 * @param inputeprParam
	 *            the inputeprParam to set
	 */
	public void setInputeprParam(final String inputeprParam) {
		this.inputeprParam = inputeprParam;
	}

	/**
	 * Gets the object store id.
	 *
	 * @return the objectStoreID
	 */
	public String getObjectStoreID() {
		return objectStoreID;
	}

	/**
	 * Sets the object store id.
	 *
	 * @param objectStoreID
	 *            the objectStoreID to set
	 */
	public void setObjectStoreID(final String objectStoreID) {
		this.objectStoreID = objectStoreID;
	}

	/**
	 * Gets the plugin.
	 *
	 * @return the plugin
	 */
	public String getPlugin() {
		return plugin;
	}

	/**
	 * Sets the plugin.
	 *
	 * @param plugin
	 *            the plugin to set
	 */
	public void setPlugin(final String plugin) {
		this.plugin = plugin;
	}

	/**
	 * Gets the protocol.
	 *
	 * @return the protol
	 */
	public String getProtocol() {
		return protocol;
	}

	/**
	 * Sets the protocol.
	 *
	 * @param protol
	 *            the protol to set
	 */
	public void setProtocol(final String protol) {
		this.protocol = protol;
	}

	/**
	 * Gets the mime type.
	 *
	 * @return the mimeType
	 */
	public String getMimeType() {
		return mimeType;
	}

	/**
	 * Sets the mime type.
	 *
	 * @param mimeType
	 *            the mimeType to set
	 */
	public void setMimeType(final String mimeType) {
		this.mimeType = mimeType;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see eu.dnetlib.msro.workflows.nodes.ProgressJobNode#getProgressProvider()
	 */
	@Override
	public ProgressProvider getProgressProvider() {
		return progressProvider;
	}

	public String getRegularExpression() {
		return regularExpression;
	}

	public void setRegularExpression(final String regularExpression) {
		this.regularExpression = regularExpression;
	}

	public int getNumberOfThreads() {
		return numberOfThreads;
	}

	public void setNumberOfThreads(final int numberOfThreads) {
		this.numberOfThreads = numberOfThreads;
	}

	public int getConnectTimeoutMs() {
		return connectTimeoutMs;
	}

	public void setConnectTimeoutMs(final int connectTimeoutMs) {
		this.connectTimeoutMs = connectTimeoutMs;
	}

	public int getReadTimeoutMs() {
		return readTimeoutMs;
	}

	public void setReadTimeoutMs(final int readTimeoutMs) {
		this.readTimeoutMs = readTimeoutMs;
	}

	public int getSleepTimeMs() {
		return sleepTimeMs;
	}

	public void setSleepTimeMs(final int sleepTimeMs) {
		this.sleepTimeMs = sleepTimeMs;
	}
}
