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

import java.util.Date;

import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import fr.gouv.culture.oai.util.OAIUtilities;

public class OAIResponseImpl extends OAIObjectImpl implements OAIResponse {

    /**The request to the repository*/
    protected OAIRequest request = null;
    /**The repository to which the request will be dispatched*/
    protected OAIRepository repository = null;
    /**The resumptionToken, if any in response*/
    protected String resumptionToken = null;
    
    protected boolean paramsError = false;
    
    protected void setResumptionToken(String rt){
    	this.resumptionToken = rt;
    }
    
    public String getResumptionToken(){
    	return this.resumptionToken;
    }

    /**Establishes the class field  for use*/
    public void setRepository(OAIRepository repository) {
        this.repository = repository;
    }

    /**Retrieves the repository*/
    public OAIRepository getRepository() {
        return this.repository;
    }

    /** Establishes the request
     * @param request The request object
     */
    public void setRequest(OAIRequest request) {
        this.request = request;
    }

    /**Retrieves the request*/
    public OAIRequest getRequest() {
        return this.request;
    }

    /**Executes the request and sends the response (SAX flow) to the consumer using the request and the repository provided*/
    public void sendResponse() throws SAXException {
        // wrapping response with envelope events
        if (this.request != null && this.repository != null) {

            int verb = this.request.getVerb();
            beginOaiEnvelopeEvents();

            if(this.paramsError) {
	            switch (verb) {
	                case OAIRequest.VERB_IDENTIFY:
	                    this.repository.identify(this.request);
	                    break;
	                case OAIRequest.VERB_LIST_SETS:
	                    this.repository.listSets(this.request);
	                    break;
	                case OAIRequest.VERB_LIST_METADATA_FORMATS:
	                    this.repository.listMetadataFormats(this.request);
	                    break;
	                case OAIRequest.VERB_LIST_IDENTIFIERS:
	                    this.repository.listIdentifiers(this.request);
	                    break;
	                case OAIRequest.VERB_LIST_RECORDS:
	                    this.repository.listRecords(this.request);
	                    break;
	                case OAIRequest.VERB_GET_RECORD:
	                    this.repository.getRecord(this.request);
	                    break;
	                default:
	                case OAIRequest.VERB_UNKNOWN:
	                    String verbString = this.request.getVerbString();
	                    String errorString = "The verb";
	                    if (OAIUtilities.checkString(verbString))
	                        errorString += ", " + verbString + ",";
	                    errorString += " is unknown or a value was not provided.";
	                    new OAIError(OAIError.ERROR_BAD_VERB, errorString).toSAX(this);
	                    break;
	
	            }
            }
            
            this.resumptionToken = this.request.getResumptionToken();

            // wrapping response with envelope events
            endOaiEnvelopeEvents();
        }

    }


    /**Just calls sendResponse()
     *
     * @see this.sendResponse()
     */
    public void toSAX(ContentHandler contentHandler) throws SAXException {
        ContentHandler currentHandler = super.contentHandler;
        //setting the handler
        super.setContentHandler(contentHandler);
        sendResponse();
        //resetting the handler
        super.setContentHandler(currentHandler);
    }


    /**Sends the start of the oai envelope*/
    protected void beginOaiEnvelopeEvents() throws SAXException {
        // <?xml version="1.0" encoding="UTF-8" ?>
        startOaiRootElement();
        sendResponseDate();
        this.paramsError = verifyParameters();
        sendRequestEvents(this.paramsError);
    }

    /**Ends the start of the oai envelope*/
    protected void endOaiEnvelopeEvents() throws SAXException {
        endOaiRootElement();
    }


    /**Sends the oai-pmh root element*/
    protected void startOaiRootElement() throws SAXException {
        /* <OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
                 http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
        */
        //NOTE: DEBUG XALAN: START
        /*old code*/
        AttributesImpl atts = new AttributesImpl();
        super.startPrefixMapping(OAIObject.Node.Prefix.XSI, OAIObject.Node.Xmlns.XSI);
        atts.addAttribute(OAIObject.Node.Xmlns.XSI, "schemaLocation", OAIObject.Node.Name.Qualified.XSI_SCHEMA_LOCATION, OAIObject.Node.Type.CDATA, OAIObject.Node.Value.XSI_SCHEMA_LOCATION_OAI_2_0);
        super.startElement(OAIObject.Node.Xmlns.OAI_2_0, OAIObject.Node.Name.OAI_PMH, OAIObject.Node.Name.OAI_PMH, atts);
        /*new code
    	AttributesImpl atts = new AttributesImpl();
        atts.addAttribute("", OAIObject.Node.Name.XMLNS, OAIObject.Node.Name.XMLNS, OAIObject.Node.Type.CDATA, OAIObject.Node.Xmlns.OAI_2_0);//xmlns="http://www.openarchives.org/OAI/2.0/"
        atts.addAttribute("", OAIObject.Node.Prefix.XSI, OAIObject.Node.Name.XMLNS+":"+OAIObject.Node.Prefix.XSI, OAIObject.Node.Type.CDATA, OAIObject.Node.Xmlns.XSI);//xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        atts.addAttribute(OAIObject.Node.Xmlns.XSI, "schemaLocation", OAIObject.Node.Name.Qualified.XSI_SCHEMA_LOCATION, OAIObject.Node.Type.CDATA, OAIObject.Node.Value.XSI_SCHEMA_LOCATION_OAI_2_0);//xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd"
        super.startElement("", OAIObject.Node.Name.OAI_PMH, OAIObject.Node.Name.OAI_PMH, atts);*/
        //NOTE: DEBUG XALAN: END
    }

    /**Ends the oai-pmh root element*/
    protected void endOaiRootElement() throws SAXException {
        //</OAI-PMH>
    	//NOTE: DEBUG XALAN: START
        /*old code*/
        super.endElement(OAIObject.Node.Xmlns.OAI_2_0, OAIObject.Node.Name.OAI_PMH, OAIObject.Node.Name.OAI_PMH);
        super.endPrefixMapping(OAIObject.Node.Prefix.XSI);
        /*new code
    	super.endElement("", OAIObject.Node.Name.OAI_PMH, OAIObject.Node.Name.OAI_PMH);*/
    	//NOTE: DEBUG XALAN: START


    }

    /**Sends teh response date element*/
    protected void sendResponseDate() throws SAXException {
        //<responseDate>2002-05-01T19:20:30Z</responseDate>
    	AttributesImpl atts = new AttributesImpl();
    	super.startElement(OAIObject.Node.Xmlns.OAI_2_0, OAIObject.Node.Name.RESPONSE_DATE, OAIObject.Node.Name.RESPONSE_DATE, atts);
    	Date date = fr.gouv.culture.oai.util.OAIUtilities.Date.getUtcIso8601Date();
    	String utcDate = fr.gouv.culture.oai.util.OAIUtilities.Date.formatUtcISO8601Date(date);
    	super.sendElementContent(utcDate);
    	super.endElement(OAIObject.Node.Xmlns.OAI_2_0, OAIObject.Node.Name.RESPONSE_DATE, OAIObject.Node.Name.RESPONSE_DATE);
    }


    /**Sends the request event
     *
     * @param sendRequestParams Whether or not to send the parameters of the request (according to error state)
     */
    protected void sendRequestEvents(boolean sendRequestParams) throws SAXException {
        if (this.request != null) {
            this.request.setConsumer(super.xmlConsumer);
            this.request.toSAX(this, sendRequestParams);
        }
    }


    /**Verifies the parameters against any expectations of the repository*/
    protected boolean verifyParameters() throws SAXException {
        if (this.repository != null)
            return this.repository.verifyParameters(this.request);
        else
            return false;
    }


}
