package eu.dnetlib.data.index;

import java.util.List;

import com.google.common.base.Function;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.CloudSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrInputDocument;

/**
 * Created by michele on 11/11/15.
 */
public class CloudIndexClient {

	private static final Log log = LogFactory.getLog(CloudIndexClient.class);
	private static final String INDEX_RECORD_RESULT_FIELD = "dnetResult";

	private final CloudSolrServer solrServer;

	protected CloudIndexClient(final CloudSolrServer solrServer) {
		this.solrServer = solrServer;
	}

	public int feed(final String record, final String indexDsId, final Function<String, String> toIndexRecord) throws CloudIndexClientException {
		try {
			final SolrInputDocument doc = prepareSolrDocument(record, indexDsId, toIndexRecord);
			if ((doc == null) || doc.isEmpty()) throw new CloudIndexClientException("Invalid solr document");
			return feed(doc);
		} catch (final Throwable e) {
			throw new CloudIndexClientException("Error feeding document", e);
		}
	}

	public int feed(final SolrInputDocument document) throws CloudIndexClientException {
		try {
			final UpdateResponse res = solrServer.add(document);
			//log.debug("feed time for single records, elapsed time: " + HumanTime.exactly(res.getElapsedTime()));
			if (res.getStatus() != 0) {
				throw new CloudIndexClientException("bad status: " + res.getStatus());
			}
			solrServer.commit();
			return res.getStatus();
		} catch (final Throwable e) {
			throw new CloudIndexClientException("Error feeding document", e);
		}
	}

	public void feed(final List<SolrInputDocument> docs, final AfterFeedingCallback callback) throws CloudIndexClientException {
		try {
			final UpdateResponse res = solrServer.add(docs);
			//log.debug("feed time for " + docs.size() + " records, elapsed tipe: : " + HumanTime.exactly(res.getElapsedTime()));
			solrServer.commit();
			if (callback != null) {
				callback.doAfterFeeding(res);
			}
			if (res.getStatus() != 0) throw new CloudIndexClientException("bad status: " + res.getStatus());
		} catch (final Throwable e) {
			throw new CloudIndexClientException("Error feeding documents", e);
		}
	}

	public SolrInputDocument prepareSolrDocument(final String record, final String indexDsId, final Function<String, String> toIndexRecord)
			throws CloudIndexClientException {
		try {
			/*
			final StreamingInputDocumentFactory documentFactory = new StreamingInputDocumentFactory();

			final String version = (new SimpleDateFormat("yyyy-MM-dd\'T\'hh:mm:ss\'Z\'")).format(new Date());
			final String indexRecord = toIndexRecord.apply(record);

			if (log.isDebugEnabled()) {
				log.debug("***************************************\nSubmitting index record:\n" + indexRecord + "\n***************************************\n");
			}

			return documentFactory.parseDocument(version, indexRecord, indexDsId, INDEX_RECORD_RESULT_FIELD);*/
			return null;
		} catch (final Throwable e) {
			throw new CloudIndexClientException("Error creating solr document", e);
		}
	}

	public boolean isRecordIndexed(final String id) throws CloudIndexClientException {
		try {
			final SolrQuery query = new SolrQuery();
			query.setQuery("objidentifier:\"" + id + "\"");
			final QueryResponse res = solrServer.query(query);
			return res.getResults().size() > 0;
		} catch (final Throwable e) {
			throw new CloudIndexClientException("Error searching documents", e);
		}
	}

	public void close() {
		if (solrServer != null) {
			solrServer.shutdown();
		}
	}

	public interface AfterFeedingCallback {

		void doAfterFeeding(final UpdateResponse response);
	}
}
