package eu.dnetlib.oai.utils;

import java.util.List;
import java.util.function.Function;

import javax.xml.transform.TransformerFactory;

import com.google.common.collect.Lists;
import eu.dnetlib.clients.enabling.ISLookUpClient;
import eu.dnetlib.enabling.locators.UniqueServiceLocator;
import eu.dnetlib.miscutils.functional.xml.ApplyXslt;
import eu.dnetlib.oai.conf.OAIConfigurationExistReader;
import eu.dnetlib.rmi.enabling.ISLookUpException;
import eu.dnetlib.rmi.enabling.ISLookUpService;
import eu.dnetlib.rmi.provision.MDFInfo;
import eu.dnetlib.rmi.provision.OaiPublisherException;
import eu.dnetlib.rmi.provision.OaiPublisherRuntimeException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.DocumentException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;

/**
 * Helper class for common queries to the IS.
 *
 * @author alessia
 */
public class OAIISLookUpClient {

	private static final Log log = LogFactory.getLog(ISLookUpClient.class); // NOPMD by marko on 11/24/08 5:02 PM

	@Value("${services.oai.publisher.db.xquery}")
	private String xpathToCurrentDB;

	/**
	 * lookup service.
	 */
	@Autowired
	private UniqueServiceLocator serviceLocator;

	@Autowired
	private OAIConfigurationExistReader configuration;

	@Autowired
	private TransformerFactory saxonTransformerFactory;

	public List<MDFInfo> listMetadataFormats(final boolean onlyEnabled) throws ISLookUpException, DocumentException, OaiPublisherException {
		return Lists.newArrayList(this.configuration.getMetadataFormatInfo(onlyEnabled));
	}

	@Cacheable(value = "unaryFunctions", key = "#tdsRuleId")
	public Function<String, String> getUnaryFunctionFromTDSRule(final String tdsRuleId) {
		log.fatal("Not using cache to get TDSRule " + tdsRuleId);
		final String queryCodeRule = "//RESOURCE_PROFILE[.//RESOURCE_IDENTIFIER/@value='" + tdsRuleId
				+ "']/BODY/CONFIGURATION/SCRIPT/CODE/*[local-name()='stylesheet']";
		String xsltCode = null;
		try {
			xsltCode = this.serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(queryCodeRule);
		} catch (final Throwable e) {
			log.fatal("Unexisting TDSRule profile with identifier " + tdsRuleId);
			throw new OaiPublisherRuntimeException(e);
		}
		if (StringUtils.isBlank(xsltCode)) {
			log.warn("Unexpected blank stylesheet in TDSRule profile with id: " + tdsRuleId + ". Returning identity function.");
			return it -> it;
		} else {
			return new ApplyXslt(xsltCode, saxonTransformerFactory);
		}
	}

	@Cacheable("oaiDB")
	public String getCurrentDB() throws ISLookUpException {
		log.fatal("Not using cache to get the current OAI db");
		String currentDBName = this.serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(xpathToCurrentDB);
		log.info("Current OAI DB:" + currentDBName);
		return currentDBName;
	}

	@CacheEvict(value = { "unaryFunctions", "oaiDB" }, allEntries = true, beforeInvocation = true)
	public void evictCaches() {
		log.info("Evicted caches oaiDB and unaryFunctions");
	}

	public OAIConfigurationExistReader getConfiguration() {
		return configuration;
	}

	public void setConfiguration(final OAIConfigurationExistReader configuration) {
		this.configuration = configuration;
	}

}
