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

import fr.gouv.culture.oai.util.OAIUtilities;
import fr.gouv.culture.sdx.exception.SDXException;
import fr.gouv.culture.sdx.exception.SDXExceptionCode;

import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.cocoon.Constants;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.xml.XMLConsumer;
import org.xml.sax.SAXException;

import java.io.File;
import java.net.MalformedURLException;

public class OAIComponentImpl implements LogEnabled, OAIComponent,
        Contextualizable, Serviceable, Configurable, /*Parameterizable,*/ Initializable,
        ThreadSafe {

    /** The component manager. */
    private ServiceManager manager = null;
    /** The compenent's context. */
    private Context context = null;
    /** The servlet "context directory" : file:/{TOMCAT_HOME}/webapps/{sdx}/. */
    private String contextPath = null;
    /** The components's working directory : {sdx}. */
    private File workDir = null;
    protected Logger logger = null;

    public void enableLogging(Logger logger) {
    	// Getting the logger
		//String logid = "oai";
		//logger = logger.getChildLogger(logid);
        this.logger = logger;
    }

    public void contextualize(Context context) throws ContextException {
        if (context == null) throw new ContextException("ContextKeys provided was null", null);

        this.context = context;

        //getting a working directory
        if (this.workDir == null) {
            //getting the default one
            this.workDir = (File) context.get(Constants.CONTEXT_WORK_DIR);
        }

        //if none was provided, get a context path
        org.apache.cocoon.environment.Context ctx =
                (org.apache.cocoon.environment.Context) context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);

        // Determine the context directory, preferably as a file
        // FIXME (SW) - this is purposely redundant with some code in CocoonServlet
        // to have the same rootPath. How to avoid this ?
        try {
            String rootPath = ctx.getRealPath("/");
            if (rootPath != null) {
                this.contextPath = new File(rootPath).toURI().toURL().toExternalForm();
            } else {
                String webInf = ctx.getResource("/WEB-INF").toExternalForm();
                this.contextPath = webInf.substring(0, webInf.length() - "WEB-INF".length());
            }
        } catch (MalformedURLException e) {
            OAIUtilities.logWarn(logger, "Could not get context directory", e);
            this.contextPath = "";
        }

    }


    public void service(ServiceManager manager) throws ServiceException {
        this.manager = manager;
    }

    public void configure(Configuration configuration) throws ConfigurationException {
    }

    public void initialize() throws Exception {
    }


    /**
     * Gets the framework's super.getLog().
     *
     * @return  The super.getLog().
     */
    public Logger getLogger() {
        return logger;
    }


    /**
     * Manages a request to an OAI repository
     * @param repo
     * @param cocoonRequest
     * @param consumer
     * @throws SAXException
     */
    public void acceptRequest(OAIRepository repo, Request cocoonRequest, XMLConsumer consumer) 
    	throws SAXException, SDXException 
	{
    	if(repo==null){
    		String[] args = {cocoonRequest.getRequestURI()+"?"+cocoonRequest.getQueryString()};
    		throw new SDXException(SDXExceptionCode.OAI_NO_OAI_REPOSITORY_ID_AVAILABLE_FOR_URL,args);
    	}
    	else if (cocoonRequest != null && consumer != null) {
    		
    		OAIUtilities.logInfo(this.logger, "Accepting request for the OAI repository "+(repo.getBaseURL())+
    				" ; Request: "+cocoonRequest.getRequestURI()+"?"+cocoonRequest.getQueryString()+
    				" ; Remote address: "+cocoonRequest.getRemoteAddr()+
    				" ; Remote host: "+cocoonRequest.getRemoteHost()
    				);
    		
            OAIRequest request = new OAIRequestImpl();
            request.enableLogging(this.logger);
            request.setRequest(cocoonRequest);

            //generating a response
            OAIResponse response = new OAIResponseImpl();
            response.enableLogging(this.logger);
            response.setRepository(repo);
            response.setRequest(request);
            //setting the consumer of the repository events
            repo.setConsumer(response);
            response.setConsumer(consumer);
            response.sendResponse();
        }
    }


    /**
     * Manages a response from an OAI harvester
     * @param requestUrl
     * @param harvester
     * @param identifierNodeName
     */
    public void receiveResponse(String requestUrl, OAIHarvester harvester, String identifierNodeName) {
    	OAIUtilities.logInfo(this.logger, "Receiving response from OAI harvester: "+identifierNodeName);
        if (harvester != null && OAIUtilities.checkString(requestUrl)) {
            harvester.setIdentifierName(identifierNodeName);
            harvester.receiveSynchronizedRequest(requestUrl);
        }

    }


}
