package eu.dnetlib.vocabularies.publisher;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;

import com.google.common.collect.Lists;

import eu.dnetlib.enabling.tools.SplittedQueryExecutor;
import eu.dnetlib.vocabularies.publisher.model.Vocabulary;
import eu.dnetlib.vocabularies.publisher.model.VocabularyTerm;

public class VocabularyRetriever {

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

	@Autowired
	private SplittedQueryExecutor queryExecutor;

	@Cacheable("vocabularies")
	public List<Vocabulary> listVocabularies() {
		log.debug("listVocabularies(): not using cache");
		String query = "for $x in collection('/db/DRIVER/VocabularyDSResources/VocabularyDSResourceType') order by $x//VOCABULARY_NAME "
				+ "return concat ($x//RESOURCE_IDENTIFIER/@value, ':-:',$x//VOCABULARY_NAME, ':-:',$x//VOCABULARY_DESCRIPTION, ':-:',$x//VOCABULARY_NAME/@code)";
		Iterable<Vocabulary> vocs = this.queryExecutor.query(Vocabulary.class, query);
		return Lists.newArrayList(vocs);
	}

	@Cacheable(value = "terms", key = "#id")
	public Vocabulary getVocabulary(final String id) throws VocabularyNotFoundException {
		log.debug("getVocabulary(): not using cache");
		// get the vocabulary info:
		String queryVoc = "let $x := /*[.//RESOURCE_IDENTIFIER/@value='"
				+ id
				+ "']"
				+ " return concat ($x//RESOURCE_IDENTIFIER/@value, ':-:',$x//VOCABULARY_NAME, ':-:',$x//VOCABULARY_DESCRIPTION, ':-:',$x//VOCABULARY_NAME/@code)";

		Vocabulary voc = getVocabularyByQuery(queryVoc);
		if (voc == null) throw new VocabularyNotFoundException("Can't find vocabulary by id: " + id);
		else return voc;
	}

	@Cacheable(value = "termsByCode", key = "#code")
	public Vocabulary getVocabularyByCode(final String code) throws VocabularyNotFoundException {
		log.debug("getVocabularyByCode(): not using cache");
		String queryVoc = "let $x := //RESOURCE_PROFILE[.//VOCABULARY_NAME/@code='"
				+ code
				+ "']"
				+ " return concat ($x//RESOURCE_IDENTIFIER/@value, ':-:',$x//VOCABULARY_NAME, ':-:',$x//VOCABULARY_DESCRIPTION, ':-:',$x//VOCABULARY_NAME/@code)";
		Vocabulary voc = getVocabularyByQuery(queryVoc);
		if (voc == null) throw new VocabularyNotFoundException("Can't find vocabulary by code: " + code);
		else return voc;
	}

	private Vocabulary getVocabularyByQuery(final String query) {
		Iterable<Vocabulary> vocs = this.queryExecutor.query(Vocabulary.class, query);
		if (vocs.iterator().hasNext()) {
			Vocabulary theVoc = vocs.iterator().next();
			if (theVoc.getId() == null) return null;
			// now the terms
			String queryTerms = "for $x in /*[.//RESOURCE_IDENTIFIER/@value='" + theVoc.getId() + "']//TERM order by $x/@english_name "
					+ "return concat ($x/@english_name,':-:',$x/@native_name,':-:',$x/@encoding,':-:',$x/@code)";
			Iterable<VocabularyTerm> terms = this.queryExecutor.query(VocabularyTerm.class, queryTerms);
			theVoc.setTerms(Lists.newArrayList(terms));
			return theVoc;
		} else return null;
	}

}
