/*
Copyright (C) 2000-2010  Ministere de la culture et de la communication (France), AJLSM
See LICENCE file
*/

package fr.gouv.culture.sdx.search.lucene.query;

import fr.gouv.culture.sdx.exception.SDXException;
import fr.gouv.culture.sdx.exception.SDXExceptionCode;
import fr.gouv.culture.sdx.utils.AbstractSdxObject;
import org.apache.lucene.search.Hits;

import java.io.IOException;


/*
 *	Les documents qui forment une liste ordonnee de resultats de recherche.
 *
 *	Cette classe permet de gerer efficacement les tris, car seules les requetes
 *	qui demandent un tri autre que la pertinence sont effectivement triees.
 */

/**
 * The documents which form an ordered list of search results.
 * This class allows one to manage the sorting effectively, because
 * only the requests which require a sorting other than the relevance
 * are actually sorted.
 */
public class ResultDocuments extends AbstractSdxObject {

    public static final String CLASS_NAME_SUFFIX = "ResultDocuments";

    /* The Lucene results, if needed */
    private Hits luceneHits;

    /** Sorted results */
    private ResultDocument[] sortedResults;

    /** The number of results */
    private int nbHits;

    /**Creates a ResultDocuments object
     *
     * <p>
     * A super.getLog() must be set and then this object must be setUp.
     *
     * @see #enableLogging
     * @see #setUp
     */
    public ResultDocuments() {
    }

    /**
     *	Builds a list of result documents from Lucene results.
     *
     *	@param	h			The Lucene results.
     */
    public void setUp(Hits h) {
        luceneHits = h;
        nbHits = h.length();
    }

    /**
     *	Builds a list of result documents from an array or sorted ResultDocuments.
     *
     *	@param	sr			The sorted results.
     */
    public void setUp(ResultDocument[] sr) {
        sortedResults = sr;
        nbHits = sr.length;
    }

    /**
     *	Sets the sorted results.
     *
     *	@param	sr			The sorted results.
     */
    public void setSortedResults(ResultDocument[] sr) {
        sortedResults = sr;
        nbHits = sr.length;
        luceneHits = null;
    }

    /**
     *	Returns the number of results.
     */
    public int getLength() {
        return nbHits;
    }

    /**
     *	Returns the relevance ranking of the first document; therefore, the highest ranking is returned.
     */
    public float getMaxScore() throws SDXException, IOException {
        return getDocument(0).getScore();
    }

    /**
     *	Returns a document according to its index in the list.
     *
     *	@param	i	The index of the desired document.
     */
    public ResultDocument getDocument(int i) throws SDXException {
        if (luceneHits != null && i < luceneHits.length()) {
            ResultDocument rDoc = null;
            try {
                if (luceneHits.doc(i) != null) {
                    rDoc = new ResultDocument();
                    rDoc.enableLogging(super.getLog());
                    rDoc.setUp(luceneHits.doc(i), luceneHits.score(i));
                }
            } catch (IOException e) {
                //we could not get the document at the index specified from the hits
                String[] args = new String[1];
                args[0] = e.getMessage();
                throw new SDXException(super.getLog(), SDXExceptionCode.ERROR_GET_LUCENE_HITS_DOC, args, e);
            } catch (ArrayIndexOutOfBoundsException e) {
                //debugging, why are we getting this from time to time with sdxworld?
                String[] args = new String[1];
                args[0] = e.getMessage();
                throw new SDXException(super.getLog(), SDXExceptionCode.ERROR_GET_LUCENE_HITS_DOC, args, e);
            }
            return rDoc;
        } else
        //TODO?:should we be checking for null in this case, what if sortedResults is null?
            return sortedResults[i];
    }

    /**
     *	Returns all of the result documents.
     */
    public ResultDocument[] getDocuments() throws SDXException {
        if (luceneHits != null) {
            ResultDocument[] ret = new ResultDocument[getLength()];
            for (int i = 0; i < getLength(); i++) {
                ResultDocument rDoc = new ResultDocument();
                rDoc.enableLogging(super.getLog());
                try {

                    rDoc.setUp(luceneHits.doc(i), luceneHits.score(i));

                } catch (IOException e) {
                    String[] args = new String[1];
                    args[0] = e.getMessage();
                    throw new SDXException(null, SDXExceptionCode.ERROR_GET_LUCENE_HITS_DOC, args, e);
                }

                ret[i] = rDoc;
            }

            return ret;
        } else
        //should we be checking for null in this case?
            return sortedResults;
    }

    protected String getClassNameSuffix() {
        return ResultDocuments.CLASS_NAME_SUFFIX;
    }

	/* (non-Javadoc)
	 * @see fr.gouv.culture.sdx.utils.AbstractSdxObject#initToSax()
	 */
	protected boolean initToSax() {
		return true;
	}

	/**Init the LinkedHashMap _xmlizable_volatile_objects with the objects in order to describ them in XML
	 * Some objects need to be refresh each time a toSAX is called*/
	protected void initVolatileObjectsToSax() {

	}

}
