/*
Copyright (C) 2000-2010  Ministere de la culture et de la communication (France), AJLSM
See LICENCE file
*/
package fr.gouv.culture.sdx.thesaurus;

import fr.gouv.culture.sdx.documentbase.SDXDocumentBase;
import fr.gouv.culture.sdx.utils.Utilities;
import fr.gouv.culture.sdx.utils.Identifiable;
import fr.gouv.culture.sdx.utils.constants.ContextKeys;
import fr.gouv.culture.sdx.exception.SDXException;
import fr.gouv.culture.sdx.exception.SDXExceptionCode;
import fr.gouv.culture.sdx.repository.Repository;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.excalibur.source.impl.URLSource;
import org.apache.cocoon.ProcessingException;
import org.xml.sax.SAXException;

import java.io.File;
import java.util.ArrayList;

public abstract class AbstractThesaurus extends SDXDocumentBase implements SDXThesaurus{

	protected int defaultDepth = 0;
	protected int[] defaultRelations;
	protected URLSource source = null;

	public void configure(Configuration configuration) throws ConfigurationException {
		//do luceneDocumentBaseConfiguration
		super.configure(configuration);
		//configuring
		//default depth param
		//default relation params
		Configuration depth = configuration.getChild(SDXThesaurus.ConfigurationNode.DEPTH, false);
		if (depth != null)
			defaultDepth = depth.getValueAsInteger(0);//<depth>n</depth> if none; then n=0

		Configuration[] relations = configuration.getChild(SDXThesaurus.ConfigurationNode.RELATIONS, true).getChildren(SDXThesaurus.ConfigurationNode.RELATION);
		if (relations != null && relations.length > 0) {
			defaultRelations = new int[relations.length];
			for (int i = 0; i < relations.length; i++) {
				String relationAbbr = relations[i].getValue();
				int relation = getRelationTypeInt(relationAbbr);
				if (relation > -1)
					defaultRelations[i] = relation;
			}
		}
	}

	/**Overrides parent method and allows for configuration element &lt;sdx:thesaurus&gt;
	 * set's the path for the this thesaurus/document base
	 *
	 * @param configuration
	 * @throws ConfigurationException
	 */
	protected void configureBase(Configuration configuration) throws ConfigurationException {
		String dbDirPath = "";
		//at this point, we have a <sdx:documentBase> configuration object...
		if (configuration.getName().equals(Utilities.getElementName(SDXThesaurus.CLASS_NAME_SUFFIX))) {
			try {
				//setting the id from the configuration file
				setId(configuration.getAttribute(Identifiable.ConfigurationNode.ID));
			} catch (SDXException sdxE) {
				throw new ConfigurationException(sdxE.getMessage(), sdxE);
			}
			if (!Utilities.checkString(getId())) {
				String[] args = new String[1];
				args[0] = configuration.getLocation();
				SDXException sdxE = new SDXException(SDXExceptionCode.ERROR_INVALID_ID_VALUE, args);
				throw new ConfigurationException(sdxE.getMessage(), sdxE);
			}
			//getting the path for the location where this document base will reside
			dbDirPath = Utilities.getStringFromContext(ContextKeys.SDX.Application.THESAURI_DIRECTORY_PATH, super.getContext()) + getId() + File.separator;
		}
		//... otherwise we have a unrecognized element
		else {
			String[] args = new String[1];
			args[0] = configuration.getName();
			//not passing a super.getLog() should be logged later up the stack
			//TODOException: create a better message here
			SDXException sdxE = new SDXException(null, SDXExceptionCode.ERROR_UNRECOGNIZED_DOCUMENTBASE_CONFIG, args, null);
			throw new ConfigurationException(sdxE.getMessage(), sdxE);
		}

		//setting property : the path where this document base resides
		super.getContext().put(ContextKeys.SDX.DocumentBase.DIRECTORY_PATH, dbDirPath);
	}

	protected Configuration[] getRepositoryConfigurationList(Configuration configuration) throws ConfigurationException {
		//at this point, we COULD have a <sdx:repositories> element containing a list of repositories, but it is not necessary
		//intializing the array
		String elementName = Utilities.getElementName(Repository.CLASS_NAME_SUFFIX);
		Configuration[] repoConfList = new Configuration[configuration.getChild(Repository.ConfigurationNode.REPOSITORIES, true).getChildren(elementName).length];
		//getting an array of configuration objects from each of the <sdx:repository> subElements of <sdx:repositories> element
		repoConfList = configuration.getChild(Repository.ConfigurationNode.REPOSITORIES, true).getChildren(elementName);
		return repoConfList;

	}



	public String getRelationTypeAbbreviation(int type) {
		switch (type) {
			case RELATION_BROADER_TERMS:
				return Concept.RELATION_BROADER_TERMS;
			case RELATION_BROADER_TERM:
				return Concept.RELATION_BROADER_TERM;
			case RELATION_NARROWER_TERM:
				return Concept.RELATION_NARROWER_TERM;
			case RELATION_USED_FOR:
				return Concept.RELATION_USED_FOR;
			case RELATION_EQUIVALENT_TERM:
				return Concept.RELATION_EQUIVALENT_TERM;
			case RELATION_RELATED_TERM:
				return Concept.RELATION_RELATED_TERM;
			case RELATION_USE:
				return Concept.RELATION_USE;
			case RELATION_PARTIAL_EQIUVALENCE:
				return Concept.RELATION_PARTIAL_EQIUVALENCE;
			default:
				return null;
		}
	}

	public int getRelationTypeInt(String abbr) {
		if (abbr.equalsIgnoreCase(Concept.RELATION_BROADER_TERMS))
			return RELATION_BROADER_TERMS;
		if (abbr.equalsIgnoreCase(Concept.RELATION_BROADER_TERM))
			return RELATION_BROADER_TERM;
		if (abbr.equalsIgnoreCase(Concept.RELATION_NARROWER_TERM))
			return RELATION_NARROWER_TERM;
		if (abbr.equalsIgnoreCase(Concept.RELATION_USE))
			return RELATION_USE;
		if (abbr.equalsIgnoreCase(Concept.RELATION_USED_FOR))
			return RELATION_USED_FOR;
		if (abbr.equalsIgnoreCase(Concept.RELATION_EQUIVALENT_TERM))
			return RELATION_EQUIVALENT_TERM;
		if (abbr.equalsIgnoreCase(Concept.RELATION_RELATED_TERM))
			return RELATION_RELATED_TERM;
		if (abbr.equalsIgnoreCase(Concept.RELATION_PARTIAL_EQIUVALENCE))
			return RELATION_PARTIAL_EQIUVALENCE;
		return -1;
	}

	/**
	 * Adds a document.
	 *
	 * @param   concept     The document to add.
	 */
	public void addConcept(Concept concept) throws SDXException {
		try {
			super.index(concept, null, null, null);
		} catch (SAXException e) {
			//no handler so no exception should occure here
		} catch (ProcessingException e) {
			//no handler so no exception should occure here
		}
	}

	public void addConcepts(Concept[] concepts) throws SDXException {
		try {
			super.index(concepts, null, null, null);
		} catch (SAXException e) {
			//no handler so no exception should occure here
		} catch (ProcessingException e) {
			//no handler so no exception should occure here
		}
	}

	/**
	 * Removes a concept document with the given id and any sub concepts.
	 *
	 * @param   concept      The document.
	 */
	public void deleteConcept(Concept concept) throws SDXException {
		try {

			super.delete(concept, null);
		} catch (SAXException e) {
			//no handler so no exception should occure here
		} catch (ProcessingException e) {
			//no handler so no exception should occure here
		}

	}

	/**
	 * Removes a concept document with the given id and any sub concepts.
	 *
	 * @param   concepts      The documents.
	 */
	public void deleteConcepts(Concept[] concepts) throws SDXException {
		try {

			super.delete(concepts, null);
		} catch (SAXException e) {
			//no handler so no exception should occure here
		} catch (ProcessingException e) {
			//no handler so no exception should occure here
		}

	}

	public Concept[] filterByLangs(Concept[] concepts, String[] langs) {
		if (concepts == null) return null;
		if (langs == null || langs.length == 0) return concepts;

		ArrayList rConcepts = new ArrayList();
		for (int i = 0; i < concepts.length; i++) {
			String xmlLang = concepts[i].getXmlLang();
			if (Utilities.checkString(xmlLang)) {
				for (int j = 0; j < langs.length; j++) {
					if (xmlLang.equals(langs[j]))
						rConcepts.add(concepts[i]);
				}
			}
		}

		if (rConcepts.size() > 0)
			return (Concept[]) rConcepts.toArray(new Concept[0]);
		else
			return null;
	}

	public int getDefaultDepth() {
		return defaultDepth;
	}

	public int[] getDefaultRelations() {
		return defaultRelations;
	}



}
