package org.apache.slide.projector.processor.process;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.slide.projector.Projector;
import org.apache.slide.projector.value.URI;
import org.apache.slide.projector.value.URIValue;
import org.jdom.Element;

public class Step {
    private static Logger logger = Logger.getLogger(Step.class.getName());

    private URI processorURI;
    private String name;
    private Map parameterConfigurations = new HashMap();
    private List routingConfigurations = new ArrayList();

    public String getName() {
        return name;
    }

    public URI getProcessorURI() {
        return processorURI;
    }

    public Map getParameterConfigurations() {
        return parameterConfigurations;
    }

    public RoutingConfiguration getRoutingConfigurationByState(String state) {
        for ( Iterator i = routingConfigurations.iterator(); i.hasNext(); ) {
            RoutingConfiguration routingConfiugration = (RoutingConfiguration)i.next();
            if ( routingConfiugration.getState().equals(state) ) {
                return routingConfiugration;
            }
        }
        return null;
    }
    
    public List getRoutingConfigurations() {
        return routingConfigurations;
    }

    public void configure(Element element) {
		name = element.getAttributeValue("id");
        processorURI = new URIValue(element.getAttributeValue("processor"));
        List loadElements = element.getChildren("load");
		for ( Iterator i = loadElements.iterator(); i.hasNext(); ) {
			Element loadElement = (Element)i.next();
            String parameterName = loadElement.getAttributeValue("parameter");
            ParameterConfiguration parameterConfiguration = new ParameterConfiguration(parameterName);
            Iterator childIterator = loadElement.getChildren().iterator();
            if ( childIterator.hasNext() ) {
            	Element valueElement = (Element)childIterator.next();
            	parameterConfiguration.configure(valueElement);
            	parameterConfigurations.put(parameterName, parameterConfiguration);
            }
		}
		List routeElements = element.getChildren("route");
		for ( Iterator i = routeElements.iterator(); i.hasNext(); ) {
			Element routeElement = (Element)i.next();
            String state = routeElement.getAttributeValue("state");
            String exception = routeElement.getAttributeValue("exception");
            String step = routeElement.getAttributeValue("step");
            String returnValue = routeElement.getAttributeValue("return");
            if (state != null) {
                RoutingConfiguration routingConfiguration = new RoutingConfiguration(state);
                if (returnValue != null) {
                    routingConfiguration.setReturnValue(returnValue);
                }
                if (step != null) {
                    routingConfiguration.setStep(step);
                }
                List saveElements = routeElement.getChildren("save");
                for ( Iterator j = saveElements.iterator(); j.hasNext(); ) {
                    Element saveElement = (Element)j.next();
                    String resultName = saveElement.getAttributeValue("result");
                    String resultStore = saveElement.getAttributeValue("store");
                    String resultDomain = saveElement.getAttributeValue("domain");
                    String resultKey = saveElement.getAttributeValue("key");
                    String timeoutAsString = saveElement.getAttributeValue("timeout");
                    long timeout = -1;
                    if ( timeoutAsString != null ) {
                        timeout = Long.valueOf(timeoutAsString).longValue();
                    }
                    ResultConfiguration resultConfiguration;
                    if (resultStore == null) {
                        resultConfiguration = new ResultConfiguration(resultName, Projector.NO_STORE, resultDomain, resultKey, timeout);
                    } else {
                        resultConfiguration = new ResultConfiguration(resultName, resultStore, resultDomain, resultKey, timeout);
                    }
                    routingConfiguration.addResultConfiguration(resultConfiguration);
                }
                routingConfigurations.add(routingConfiguration);
            } else if (exception != null) {
                try {
                    Class clazz = Class.forName(exception);
                    routingConfigurations.add(new RoutingConfiguration(clazz, step));
                } catch (ClassNotFoundException e) {
                    logger.log(Level.SEVERE, "Could not find exception class=" + exception + ", skipping exception routing");
                }
            }
		}
    }
}
