package eu.dnetlib.index.action;

import java.util.Map;
import java.util.UUID;

import eu.dnetlib.enabling.resultset.client.ResultSetClient;
import eu.dnetlib.enabling.tools.blackboard.BlackboardJob;
import eu.dnetlib.enabling.tools.blackboard.BlackboardServerAction;
import eu.dnetlib.enabling.tools.blackboard.BlackboardServerHandler;
import eu.dnetlib.index.actors.*;
import eu.dnetlib.index.feed.FeedMode;
import eu.dnetlib.rmi.common.ResultSet;
import eu.dnetlib.rmi.provision.IndexServiceException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * The Class FeedIndexAction.
 */
public class FeedIndexAction extends AbstractIndexAction implements BlackboardServerAction<IndexAction> {

	/**
	 * The Constant log.
	 */
	private static final Log log = LogFactory.getLog(FeedIndexAction.class);

	/**
	 * The actor map.
	 */
	@Autowired
	private ActorMap actorMap;

	/**
	 * The feed actor factory.
	 */
	@Autowired
	private IndexFeedActorFactory feedActorFactory;

	/**
	 * The result set client factory.
	 */
	@Autowired
	private transient ResultSetClient resultSetClient;

	/**
	 * {@inheritDoc}
	 *
	 * @see BlackboardServerAction#execute(BlackboardServerHandler,
	 * BlackboardJob)
	 */
	@Override
	public void execute(final BlackboardServerHandler handler, final BlackboardJob job) throws Exception {
		handler.ongoing(job);
		log.info("FEED job set to ONGOING");

		final String epr = getEpr(job);
		final String triggerId = UUID.randomUUID().toString();
		final String dsId = getIndexDSId(job);
		final FeedMode feedMode = getFeedMode(job);
		final String backendId = getBackend(job);
		final boolean emptyResult = getEmptyResult(job);
		if (backendId == null) throw new IndexServiceException("No backend identifier information in CREATE message");

		log.debug("\n\n scheduling resultSet keepalive trigger: " + triggerId + "\n\n");
		if (!actorMap.hasActor(backendId)) {
			actorMap.addActor(backendId, feedActorFactory.newInstance());
		}

		final ResultSet<?> resultSet = ResultSet.fromJson(epr);

		final Iterable<String> records = resultSetClient.iter(resultSet, String.class);

		actorMap.getActor(backendId)
				.feedIndex(dsId, feedMode, records, null, newBBActorCallback(handler, job), backendId, emptyResult);
	}

	private boolean getEmptyResult(BlackboardJob job) {

		if (job.getParameters().containsKey("emptyResult")) {
			final String emptyResult = job.getParameters().get("emptyResult").toLowerCase().trim();
			return "true".equals(emptyResult);

		} else return false;
	}

	/**
	 * Constructor for a blackboard callback to handle the job termination.
	 *
	 * @param handler the handler
	 * @param job     the BB job.
	 * @return a new eu.dnetlib.index.solr.actors.BlackboardActorCallback
	 */
	private BlackboardActorCallback newBBActorCallback(final BlackboardServerHandler handler, final BlackboardJob job) {
		return new BlackboardActorCallback() {

			@Override
			public void setJobDone(final Map<String, String> params) {
				log.info(job.getAction() + " job set to DONE");
				job.getParameters().put("added", "" + params.get("added"));
				job.getParameters().put("skipped", "" + params.get("skipped"));
				job.getParameters().put("marked", "" + params.get("marked"));
				job.getParameters().put("time", "" + params.get("time"));
				handler.done(job);
			}

			@Override
			public void setJobFailed(final Throwable exception) {
				log.error(job.getAction() + " job set to FAILED ", exception);
				handler.failed(job, exception);
			}
		};
	}

}
