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

import fr.gouv.culture.sdx.document.Document;
import fr.gouv.culture.sdx.exception.SDXException;
import fr.gouv.culture.sdx.utils.Utilities;
import fr.gouv.culture.sdx.utils.constants.Node;
import fr.gouv.culture.sdx.utils.database.Property;
import org.apache.excalibur.xml.sax.SAXParser;
import org.apache.cocoon.xml.XMLConsumer;

import java.util.Enumeration;
import java.util.Locale;

/**
 * Definition of an SDX user.
 *
 * <p>
 * A user is defined by the contents of an XML document. Once this document is
 * transformed during indexing, it must return a <code>name</code>. This is the
 * only restriction for a user definition document and its accompanying
 * transformation : the application developer is free to put any other information
 * within the XML document, and index it as he or she wishes.
 * <p>
 * Users are authentificated against a password, but this password is not kept within
 * the XML definition document. It is given to the application when the user is
 * added or updated. It is the responsibility of the application to manage
 * users and passwords.
 * <p>
 * A user may be a member of one or more groups. Once again, the relationships
 * between users and groups are not kept within the user definition file, but
 * managed by the application.
 * <p>
 * For compatibility reasons, this class can manage the following user properties:
 * <ul>
 * <li>The username
 * <li>The first name
 * <li>The last name
 * <li>The E-Mail
 * <li>The preferred language (a code)
 * </ul>
 * <p>
 * But in SDX 2, the most important property is the preferred locale, which
 * may be used in setting the current locale of a given acceptRequest. The preferred
 * locale is defined with the <code>language</code>, <code>country</code> and
 * <code>variant</code> fields derived from the value of xml:lang when the user is indexed.
 */
public class User extends AbstractIdentity {

    /**Gets the docType for the document*/
    public String getDocType() {
        return Document.DOCTYPE_USER;
    }

    /** The preferred locale. */
    private Locale preferredLocale;

    /**The xml:lang attribute value from which the locale is built*/
    private String xmlLang = "";

    /** The first name. */
    private String firstname;

    /** The last name. */
    private String lastname;

    /**The email address*/
    private String email;

    /** A character buffer for element content. */
    // FIXME : private object never used locally [MP] 
    private StringBuffer characterBuffer;

    /** THe current field name */
    // FIXME : private object never used locally [MP]
    private String currentFieldName;

    /** The code from the field in document(application.xconf)/sdx:application/sdx:userDocumentBase/sdx:fieldList/sdx:field[@code='firstname']*/
    public final static String XCONF_FIRSTNAME = Node.Name.FIRSTNAME;

    /** The code from the field in document(application.xconf)/sdx:application/sdx:userDocumentBase/sdx:fieldList/sdx:field[@code='lastname']*/
    public final static String XCONF_LASTNAME = Node.Name.LASTNAME;

    /** The code from the field in document(application.xconf)/sdx:application/sdx:userDocumentBase/sdx:fieldList/sdx:field[@code='email']*/
    public final static String XCONF_EMAIL = Node.Name.EMAIL;

//    /** The code from the field in document(application.xconf)/sdx:application/sdx:userDocumentBase/sdx:fieldList/sdx:field[@code='language']*/
//    public final static String ELEMENT_LANGUAGE = "language";
//
//    /** The code from the field in document(application.xconf)/sdx:application/sdx:userDocumentBase/sdx:fieldList/sdx:field[@code='country']*/
//    public static final String ELEMENT_COUNTRY = "country";

    /** The code from the field in document(application.xconf)/sdx:application/sdx:userDocumentBase/sdx:fieldList/sdx:field[@code='lang']*/
    public final static String XCONF_LANG = "lang"; //TODO : move to constants ? -pb

    /** The code from the field in document(application.xconf)/sdx:application/sdx:userDocumentBase/sdx:fieldList/sdx:field[@code='variant']*/
    public final static String XCONF_VARIANT = "variant"; //TODO : move to constants ? -pb

    /**
     * Creates an empty user. The username and other relevant informations will be supplied at
     * indexation time.
     *
     * If logging is desired the super.getLog() should be set after user creation.
     * @see #enableLogging
     */
    public User() throws SDXException {
        super();
    }

    /**
     * Creates a user given a username. Another username may be supplied at indexing time.
     *
     * @param   username      The username to use.
     *
     * If logging is desired the super.getLog() should be set after user creation.
     * @see #enableLogging
     */
    public User(String username) throws SDXException {
        super(username);
    }

    /**
     * Starts the indexing process. For users, it must return at least a "id" field.
     *
     * <p>
     * Indexing is done in the usual way but at the end we keep specific
     * user information and make them available for the getters.
     *
     * @param   parser      A parser that can be used for the indexing.
     * @param   consumer    The consumer that will receive the indexing process (may be <code>null</code>. The previously provided consumer will then be used)
     */
    public void startIndexing(SAXParser parser, XMLConsumer consumer) throws SDXException {
        // First, call the super method for normal indexing.
        super.startIndexing(parser, consumer);
        // Then keep the relevant information.
        Enumeration values = this.getFieldValues();
        if (values != null) {
            // Keep information about language, country and locale until the end of the loop
            String xmlLang = "";
            //String country = "";
            String variant = "";

            // The relevant informations should now be in the field values
            while (values.hasMoreElements()) {
                Property prop = (Property) values.nextElement();
                String name = prop.getName();
                /* if (name.equals(ELEMENT_NAME)) setName(prop.getValue());  */
                if (name.equals(XCONF_FIRSTNAME)) this.firstname = prop.getValue();
                if (name.equals(XCONF_LASTNAME)) this.lastname = prop.getValue();
                //if (name.equals(ELEMENT_LANGUAGE)) lang = prop.getValue();
                //if (name.equals(ELEMENT_COUNTRY)) country = prop.getValue();
                //the value of this property should be in the xml:lang format
                if (name.equals(XCONF_LANG)) xmlLang = prop.getValue();
                if (name.equals(XCONF_VARIANT)) variant = prop.getValue();
                if (name.equals(XCONF_EMAIL)) this.email = prop.getValue();
            }

            // If we have an xmlLang and variant information, build the preferred locale
            this.preferredLocale = Utilities.buildLocale(xmlLang, variant, null);
            this.xmlLang = xmlLang;
        }
    }

    /**
     * Returns the user's language.
     */
    public String getXmlLang() {
        return this.xmlLang;
    }

    /**
     * Returns the user's firstname.
     */
    public String getFirstname() {
        return firstname;
    }

    /**
     * Returns the user's lastname.
     */
    public String getLastname() {
        return lastname;
    }

    /**
     * Returns the user's preferred locale.
     */
    public Locale getPreferredLocale() {
        return this.preferredLocale;
    }

    /**Returns the user's email. */
    public String getEmail() {
        return email;
    }

    /**Sets the user's email*/
    public void setEmail(String email) {
        this.email = email;
    }
    //TODO : is it a superfluous setter or do we lack other getters ?

}
