/*
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.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;

import java.io.IOException;

/** Information regarding a term of a search index */
public class TermInfo extends AbstractSdxObject {

    public static final String CLASS_NAME_SUFFIX = "TermInfo";

    /** The number of documents containing this term */
    private int frequency = 0;

    /** The field name */
    private String fieldname;

    /**
     * The term content */
    private String content;

    /** A Lucene term */
    private Term term;

    /** Identify a simple document relative to a term. */
    private String docId = "";
    private String dbId = "";
    private String appId = "";

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

    /**
     *	Builds the TermInfo from an index reader and a term.
     *
     *	@param	field	The field name.
     *	@param value	The value.
     */
    public void setUp(String field, String value) throws SDXException {
        this.fieldname = field;
        this.content = value;
        this.term = new Term(this.fieldname, this.content);
    }

    /**
     *	Builds the TermInfo from an index reader and a term.
     *
     *	@param	reader	The index reader.
     *	@param term		The Lucene term.
     */
    public void setUp(IndexReader reader, Term term) throws SDXException {
        this.term = term;
        content = term.text();
        fieldname = term.field();
        //TODOException?:should we be checking for a null reader here and giving the an exeption?-rbp
        if (reader != null) {
            try {
                frequency = reader.docFreq(term);
            } catch (IOException e) {
                String[] args = new String[1];
                args[0] = e.getMessage();
                throw new SDXException(null, SDXExceptionCode.ERROR_SETUP_TERMINFO, args, e);
            }
            if (frequency == 1) setDocId(reader);
        }
    }

    /**
     *	Builds an object from a filtered term.
     *
     *	@param	reader	The index reader.
     *	@param term		The Lucene term.
     *	@param nb		The number of documents.
     */
    public void setUp(IndexReader reader, Term term, int nb) throws SDXException {
        this.term = term;
        frequency = nb;
        content = term.text();
        fieldname = term.field();
        if (reader != null && frequency == 1) setDocId(reader);
    }

    public void setDocId(String docId) {
        this.docId = docId;
    }

    public void setDbId(String dbId) {
        this.dbId = dbId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    /**
     *	Returns the number of documents in which the term is found.
     */
    public int getDocFrequency() {
        return frequency;
    }

    /**
     *	Returns the field name for this term.
     */
    public String getField() {
        return fieldname;
    }

    /**
     *	Returns the content of the term.
     */
    public String getContent() {
        return content;
    }

    /**
     *	Returns the Lucene term.
     */
    public Term getTerm() {
        return term;
    }

    /**
     *	Returns a document id.
     */
    public String getDocId() {
        return docId;
    }

    /**
     *	Returns a document base id.
     */
    public String getDbId() {
        return dbId;
    }

    /**
     *	Returns an application id.
     */
    public String getAppId() {
        return appId;
    }

    /**
     *	Sets the _identifier by the _identifier of first document which contains the term.
     *
     *	@param	reader		The index reader.
     */
    private void setDocId(IndexReader reader) throws SDXException {
        TermDocs docs = null;
        try {
            docs = reader.termDocs(term);
            if (docs.next()) {
                int iDoc = docs.doc();
                Document doc = reader.document(iDoc);
                if (doc != null) {
                    Field idField = doc.getField("sdxdocid");
                    if (idField != null) docId = idField.stringValue();
                    idField = doc.getField("sdxdbid");
                    if (idField != null) dbId = idField.stringValue();
                    idField = doc.getField("sdxappid");
                    if (idField != null) appId = idField.stringValue();
                }
            }

        } catch (IOException e) {
            String[] args = new String[2];
            args[0] = term.text();
            args[1] = e.getMessage();
            throw new SDXException(null, SDXExceptionCode.ERROR_TERMINFO_SETDOCID, args, e);
        } finally {
            //freeing the resources
            try {
                if (docs != null) docs.close();
            } catch (IOException e) {
                String[] args = new String[2];
                args[0] = term.text();
                args[1] = e.getMessage();
                throw new SDXException(null, SDXExceptionCode.ERROR_LUCENE_TERMDOCS_CLOSE, args, e);

            }
        }
    }

    /**
     * Updates the information from a new occurrence of a term (in another document base usually).
     *
     * @param r     The index reader.
     * @param t     The Lucene term.
     */
    public void update(IndexReader r, Term t) {
        try {
            if (r != null) frequency += r.docFreq(t);
        } catch (IOException e) {
            // Do nothing here ; the docuemnt frequency won't be updated but that's not too bad
        }
    }

    /**
     * Updates the information from a new occurrence of a term (in another document base usually).
     *
     * @param field     The field name.
     * @param value     The value.
     */
    public void update(String field, String value) {
        if (this.fieldname.equals(field) && this.content.equals(value))
            frequency++;
    }

    protected String getClassNameSuffix() {
        return TermInfo.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() {
	
	}

}

