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

import java.util.Map;

import org.apache.commons.contract.Context;
import org.apache.commons.contract.Result;
import org.apache.commons.contract.constraints.ArrayConstraints;
import org.apache.commons.contract.constraints.BooleanConstraints;
import org.apache.commons.contract.constraints.StringConstraints;
import org.apache.commons.contract.descriptor.ParameterDescriptor;
import org.apache.commons.contract.i18n.ParameterMessage;
import org.apache.slide.projector.constraints.URIConstraints;
import org.apache.slide.projector.context.ProjectorContext;
import org.apache.slide.projector.processor.ConfigurationException;
import org.apache.slide.projector.processor.TemplateRenderer;
import org.apache.slide.projector.processor.process.Process;
import org.apache.slide.projector.value.Streamable;
import org.apache.slide.projector.value.URI;

/**
 * @version $Revision: 1.5 $
 */

public abstract class Trigger extends TemplateRenderer {
	public final static String INSTRUCTION = "instruction";
    public final static String ACTION = "action";
    public final static String VALIDATE = "validate";
    public final static String WIZARD = "wizard";
	public final static String INVOLVED_PARAMETERS = "involvedParameters";
	public final char SEPARATOR = ';';
	
    private ParameterDescriptor[] parameterDescriptors;

    public Trigger() {
        setRequiredFragments(new String[] { getName() });
    }

    public Result process(Map parameter, Context context) throws Exception {
    	Object []involvedParameters = (Object[])parameter.get(INVOLVED_PARAMETERS);
    	String targetStep = parameter.get(Process.STEP).toString();
    	Boolean validate = (Boolean)parameter.get(VALIDATE);
    	Boolean wizard = (Boolean)parameter.get(WIZARD);
    	URI actionUri = (URI)parameter.get(ACTION);
		StringBuffer buffer = new StringBuffer(128);
		buffer.append(actionUri).append(SEPARATOR).append(validate).append(SEPARATOR).append(wizard).append(SEPARATOR).append(((ProjectorContext)context).getStep()).append(SEPARATOR).append(targetStep).append(SEPARATOR).append(((ProjectorContext)context).getProcess());
    	if ( validate.booleanValue() ) {
    		for ( int i = 0; i < involvedParameters.length; i++ ) {
    			buffer.append(SEPARATOR).append(involvedParameters[i]);
    		}
    	}
		String instruction = buffer.toString();
		parameter.put(INSTRUCTION, new String(instruction));
        return new Result(OK, OUTPUT, renderFragment(getName(), parameter));
    }
    
    public void configure(Streamable config) throws ConfigurationException {
        super.configure(config);
        ParameterDescriptor[] parentParameterDescriptors = super.getParameterDescriptors();
        parameterDescriptors = new ParameterDescriptor[parentParameterDescriptors.length + 4];
        int counter = 0;
        for ( int i = 0; i < parentParameterDescriptors.length; i++ ) {
            if (!parentParameterDescriptors[i].getName().equals(FRAGMENT)) {
                parameterDescriptors[counter] = parentParameterDescriptors[i];
                counter++;
            }
        }
        parameterDescriptors[parentParameterDescriptors.length - 1] =
                new ParameterDescriptor(ACTION, new ParameterMessage("trigger/action"), new URIConstraints());
        parameterDescriptors[parentParameterDescriptors.length ] =
            new ParameterDescriptor(Process.STEP, new ParameterMessage("trigger/step"), new StringConstraints());
        parameterDescriptors[parentParameterDescriptors.length + 1] =
            new ParameterDescriptor(VALIDATE, new ParameterMessage("trigger/validate"), new BooleanConstraints(), Boolean.TRUE);
        parameterDescriptors[parentParameterDescriptors.length + 2] =
            new ParameterDescriptor(INVOLVED_PARAMETERS, new ParameterMessage("trigger/involvedParameters"), new ArrayConstraints(new StringConstraints()));
        parameterDescriptors[parentParameterDescriptors.length + 3] =
            new ParameterDescriptor(WIZARD, new ParameterMessage("trigger/wizard"), new BooleanConstraints(), Boolean.FALSE);
    }

    public ParameterDescriptor[] getParameterDescriptors() {
        return parameterDescriptors;
    }

    protected abstract String getName();
}