/*
 * Copyright 2004-2005 the original author or authors.
 * 
 * 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.codehaus.groovy.grails.web.pageflow;

import grails.pageflow.Flow;
import grails.pageflow.State;
import grails.pageflow.Transition;
import groovy.lang.Closure;
import groovy.lang.GroovyObject;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.codehaus.groovy.grails.commons.GrailsPageFlowClass;
import org.codehaus.groovy.grails.web.pageflow.action.GrailsFormAction;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
import org.springframework.webflow.Action;
import org.springframework.webflow.AnnotatedAction;
import org.springframework.webflow.FlowAttributeMapper;
import org.springframework.webflow.config.AbstractFlowBuilder;
import org.springframework.webflow.config.FlowBuilderException;

/**
 * 
 * 
 * @author Steven Devijver
 * @since Jul 9, 2005
 */
public class GrailsFlowBuilder extends AbstractFlowBuilder implements ApplicationContextAware {

	private static final String FLOW = "flow";
	private static final String METHOD = "method";
	private static final String BIND_AND_VALIDATE = "bindAndValidate";
	private static final String VALIDATOR = "validator";
	
	private ApplicationContext applicationContext = null;
	private GrailsPageFlowClass pageFlowClass = null;
	
	public GrailsFlowBuilder() {
		super();
	}

	public void setPageFlowClass(GrailsPageFlowClass pageFlowClass) {
		this.pageFlowClass = pageFlowClass;
	}
	
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;
	}
	
	protected String flowId() {
		return this.pageFlowClass.getFlowId();
	}

	public void buildStates() throws FlowBuilderException {
		GroovyObject pageFlow = (GroovyObject)this.applicationContext.getBean(pageFlowClass.getFullName());
		Assert.notNull(pageFlow);
		Flow flow = (Flow)pageFlow.getProperty(FLOW);
		Assert.notNull(flow);
		String firstState = null;
		
		for (Iterator iter = flow.getStates().iterator(); iter.hasNext();) {
			State state = (State)iter.next();
			
			if (firstState == null) {
				firstState = state.getId();
			}
			
			if (state.isActionState()) {
				AnnotatedAction action = null;
				
				if (state.getAction() != null) {
					action = new AnnotatedAction(state.getAction());
				} else if (state.getActionClass() != null) {
					Action tmpAction = null;
					if (Action.class.isAssignableFrom(state.getActionClass())) {
						tmpAction = (Action)BeanUtils.instantiateClass(state.getActionClass());
					} else {
						throw new UnsupportedOperationException("None " + Action.class.getName() + " action classes are not yet supported!");
					}
					if (state.getActionProperties() != null) {
						new BeanWrapperImpl(tmpAction).setPropertyValues(state.getActionProperties());
					}
					action = new AnnotatedAction(tmpAction);
				} else if (state.getActionClosure() != null) {
					action = new AnnotatedAction(new ClosureAction(this.pageFlowClass.getFlowId(), state.getId(), state.getActionClosure()));
				} else if (state.getActionFormDetails() != null) {
					GrailsFormAction formAction = new GrailsFormAction();
					BeanWrapper beanWrapper = new BeanWrapperImpl(formAction);
					for (Iterator iter2 = state.getActionFormDetails().entrySet().iterator(); iter2.hasNext();) {
						Map.Entry entry = (Map.Entry)iter2.next();
						if (VALIDATOR.equals(entry.getKey()) && entry.getValue() instanceof Closure) {
							beanWrapper.setPropertyValue((String)entry.getKey(), new ClosureValidator(((Closure)entry.getValue())));
						} else {
							beanWrapper.setPropertyValue((String)entry.getKey(), entry.getValue());
						}
					}
					formAction.afterPropertiesSet();
					action = new AnnotatedAction(formAction);
					if (state.getActionMethod() != null) {
						action.setProperty(METHOD, state.getActionMethod());
					} else {
						action.setProperty(METHOD, BIND_AND_VALIDATE);
					}
				} else {
					throw new UnsupportedOperationException();
				}
						
				addActionState(state.getId(), action, getTransitions(state.getTransitions()));
			} else if (state.isViewState()) {
				if (state.getViewName() != null) {
					addViewState(state.getId(), new ModelViewDescriptorCreator(state.getViewName(), state.getViewModel()), getTransitions(state.getTransitions()), new HashMap());
				} else if (state.getViewClosure() != null) {
					throw new UnsupportedOperationException("View closures are not yet supported!");
				}
			} else if (state.isDecisionState()) {
				throw new UnsupportedOperationException("Decision states are not yet supported!");
			} else if (state.isSubflowState()) {
				if (state.getSubFlowInput() != null || state.getSubFlowOutput() != null) {
					addSubflowState(
							state.getId(), 
							getFlowServiceLocator().getFlow(state.getSubFlowId()), 
							new ClosureFlowAttributeMapper(this.pageFlowClass.getFlowId(), state.getId(), state.getSubFlowInput(), state.getSubFlowOutput()),
							getTransitions(state.getTransitions()));
				} else if (state.getAttributeMapper() != null) {
					addSubflowState(
							state.getId(),
							getFlowServiceLocator().getFlow(state.getSubFlowId()),
							state.getAttributeMapper(),
							getTransitions(state.getTransitions()));
				} else if (state.getAttributeMapperClass() != null) {
					FlowAttributeMapper flowAttributeMapper = (FlowAttributeMapper)BeanUtils.instantiateClass(state.getAttributeMapperClass());
					if (state.getAttributeMapperProperties() != null) {
						new BeanWrapperImpl(flowAttributeMapper).setPropertyValues(state.getAttributeMapperProperties());
					}
					addSubflowState(
							state.getId(),
							getFlowServiceLocator().getFlow(state.getSubFlowId()),
							flowAttributeMapper,
							getTransitions(state.getTransitions()));
				} else {
					addSubflowState(state.getId(), getFlowServiceLocator().getFlow(state.getSubFlowId()), getTransitions(state.getTransitions()));
				}
			} else if (state.isEndState()) {
				if (state.getViewName() != null) {
					addEndState(state.getId(), new ModelViewDescriptorCreator(state.getViewName(), state.getViewModel()), new HashMap());
				} else {
					addEndState(state.getId());
				}
			} else {
				throw new UnsupportedOperationException();
			}
		}
		if (firstState != null) {
			getFlow().setStartState(firstState);
		}
	}

	private org.springframework.webflow.Transition[] getTransitions(List transitions) {
		org.springframework.webflow.Transition[] transitionArray = new org.springframework.webflow.Transition[transitions.size()];
		int i = 0;
		for (Iterator iter2 = transitions.iterator(); iter2.hasNext(); i++) {
			Transition transition = (Transition)iter2.next();
			transitionArray[i] = on(transition.getName(), transition.getTargetStateId());
		}
		return transitionArray;
	}
}
