/*
 *
 * ====================================================================
 *
 * Copyright 2004 The Apache Software Foundation 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.apache.slide.projector;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.i18n.LocalizedError;
import org.apache.slide.projector.context.ProjectorContext;
import org.apache.slide.projector.context.SystemContext;
import org.apache.slide.projector.processor.ConfigurationException;
import org.apache.slide.projector.repository.Configurable;
import org.apache.slide.projector.repository.Repository;
import org.apache.slide.projector.value.URI;
import org.apache.slide.projector.value.URIValue;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

public class Projector {
    public static final String PROCESS_ID_PARAMETER = "_process_id_";
    public static final String STEP_PARAMETER = "step";
    public static final int PROCESS_ID_LENGTH = 12;
    public static final URI DEFAULT_FORM_HANDLER = new URIValue("formHandler");

    public final static String NO_STORE = "none";
    public final static String REQUEST_PARAMETER_STORE = "request-parameter"; // Reqeust parameter (can only be of type String or String[])
    public final static String REQUEST_ATTRIBUTE_STORE = "request-attribute"; // Request attribute
    public final static String REQUEST_HEADER_STORE = "request-header";
    public final static String SESSION_STORE = "session";
    public final static String COOKIE_STORE = "cookie";
    public final static String CONTEXT_STORE = "context";
    public final static String CACHE_STORE = "cache";
    public final static String REPOSITORY_STORE = "repository";
    public final static String INPUT_STORE = "input";
    public final static String OUTPUT_STORE = "output";
    public final static String TRANSIENT_PROCESS_STORE = "process"; // Transient information bound to the instance of the current process
    public final static String PERSISTENT_PROCESS_STORE = "persistent-process"; // Persistent information bound to the instance of the current process
    public final static String FORM_STORE = "form";
    public final static String STEP_STORE = "step";

    public static final String []STORES = new String[] { 
            REQUEST_PARAMETER_STORE, 
            REQUEST_ATTRIBUTE_STORE, 
            REQUEST_HEADER_STORE, 
            SESSION_STORE,
            COOKIE_STORE, 
            CONTEXT_STORE, 
            CACHE_STORE,
            REPOSITORY_STORE, 
            INPUT_STORE, 
            OUTPUT_STORE,
            TRANSIENT_PROCESS_STORE,
            PERSISTENT_PROCESS_STORE, 
            FORM_STORE, 
            STEP_STORE
            };

    private final static Logger logger = Logger.getLogger(Projector.class.getName());

    private static Credentials credentials;
    private static Repository repository;
	private static String projectorDir, applicationsDir, workDir;
	private static SystemContext systemContext;
	
	public static void configure(InputStream configuration) throws ConfigurationException {
        logger.log(Level.INFO, "Starting projector");
        Logger rootLogger = Logger.getLogger("org.apache.slide"); 
        rootLogger.setLevel(Level.ALL);
        ConsoleHandler handler = new ConsoleHandler();
        handler.setLevel(Level.ALL);
//        rootLogger.addHandler(handler);
        SAXBuilder saxBuilder = new SAXBuilder();
        try {
        	Document document = saxBuilder.build(configuration);
        	Element credentialsElement = document.getRootElement().getChild("credentials");
        	String user = credentialsElement.getAttributeValue("user");
        	String password = credentialsElement.getAttributeValue("password");
            credentials = new UsernamePasswordCredentials(user, password);
        	Element repositoryElement = document.getRootElement().getChild("repository");
        	String repositoryClassname = repositoryElement.getAttributeValue("class");
        	Class repositoryClass = Class.forName(repositoryClassname);
        	Method getInstanceMethod = repositoryClass.getMethod("getInstance", new Class[0]);
        	repository = (Repository)getInstanceMethod.invoke(null, null);
        	Element configurationElement = repositoryElement.getChild("configuration");
        	if ( repository instanceof Configurable ) {
        		((Configurable)repository).configure(configurationElement);
        	}
        	Element pathsElement = repositoryElement.getChild("paths");
        	projectorDir = pathsElement.getChildText("projector"); 
        	applicationsDir = pathsElement.getChildText("applications"); 
        	workDir = pathsElement.getChildText("work"); 
        	systemContext = new SystemContext(credentials);
        } catch (Exception e) {
        	throw new ConfigurationException(new LocalizedError("projector/configurationFailed"), e);
        }
	}
	
	public static Repository getRepository() {
        return repository;
	}
	
	public static String getApplicationsDir() {
		return applicationsDir;
	}
	
	public static String getProjectorDir() {
		return projectorDir;
	}
	
	public static String getWorkDir() {
		return workDir;
	}

	public static Credentials getCredentials() {
		return credentials;
	}

    public static ProjectorContext getSystemContext() {
        return systemContext;
    }
}