package eu.dnetlib.index.query;

import java.util.List;
import java.util.Map;

import eu.dnetlib.clients.index.query.IndexQuery;
import eu.dnetlib.clients.index.utils.IndexFieldUtility;
import eu.dnetlib.cql.lucene.QueryOptions;
import eu.dnetlib.cql.lucene.TranslatedQuery;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;

/**
 * The Class SolrIndexQuery.
 *
 * @author claudio, sandro
 */
public class SolrIndexQuery extends SolrQuery implements IndexQuery {

	/**
	 * The Constant serialVersionUID.
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * logger.
	 */
	private static final Log log = LogFactory.getLog(SolrIndexQuery.class);

	/**
	 * Instantiates a new solr index query.
	 *
	 * @param query   the query
	 * @param options the options
	 */
	public SolrIndexQuery(final TranslatedQuery query, final Map<String, List<String>> options) {
		this(query.asLucene(), options);

		setCqlParams(query.getOptions());

		log.debug("internal solr query: " + this.toString());
	}

	/**
	 * Instantiates a new solr index query.
	 *
	 * @param query   the query
	 * @param options the options
	 */
	public SolrIndexQuery(final String query, final Map<String, List<String>> options) {
		this(query);

		// TODO verify that the input options belongs to solr
		super.add(getQueryParams(options));
	}

	/**
	 * Instantiates a new solr index query.
	 *
	 * @param query the query
	 */
	public SolrIndexQuery(final String query) {
		super(query);
	}

	@Override
	public IndexQuery setQueryOffset(final int offset) {
		super.setStart(offset);
		return this;
	}

	@Override
	public IndexQuery setQueryLimit(final int limit) {
		super.setRows(limit);
		return this;
	}

	@Override
	public IndexQuery setQueryFacetLimit(final int limit) {
		super.setFacetLimit(limit);
		return this;
	}

	@Override
	public IndexQuery setQueryFacetOffset(final int offset) {
		super.set("facet.offset", offset);
		return this;
	}

	@Override
	public IndexQuery setDSIdFilters(final List<String> dsIds) {
		if (!isAll(dsIds)) {
			for (String id : dsIds) {
				addFilterQuery(IndexFieldUtility.DS_ID + ":\"" + id + "\"");
			}
		}
		return this;
	}

	/**
	 * Checks if is all.
	 *
	 * @param dsIds the ds id
	 * @return true, if is all
	 */
	protected boolean isAll(final List<String> dsIds) {
		return (dsIds != null) && (!dsIds.isEmpty()) && (dsIds.size() == 1) && dsIds.get(0).equalsIgnoreCase(IndexFieldUtility.INDEX_DSID_ALL);
	}

	/**
	 * Convert our option map to a solr option parameter map.
	 *
	 * @param options input paramter map.
	 * @return solr option parameter map.
	 */
	private SolrParams getQueryParams(final Map<String, List<String>> options) {
		ModifiableSolrParams params = new ModifiableSolrParams();
		String[] typeTag = new String[] {};

		for (Map.Entry<String, List<String>> entry : options.entrySet()) {
			params.add(entry.getKey(), entry.getValue().toArray(typeTag));
		}
		return params;
	}

	/**
	 * Sets the query options.
	 *
	 * @param options the options.
	 */
	private void setCqlParams(final QueryOptions options) {
		if (options != null) {
			if (options.getSort() != null) {
				super.addSort(options.getSort().getField(), ORDER.valueOf(options.getSort().getMode().name()));
			}
		}
	}

}
