package org.apache.slide.projector.processor;

import java.util.Iterator;
import java.util.Map;
import java.util.logging.Logger;

import org.apache.commons.contract.Context;
import org.apache.commons.contract.Result;
import org.apache.commons.contract.constraints.ArrayConstraints;
import org.apache.commons.contract.descriptor.ParameterDescriptor;
import org.apache.commons.contract.descriptor.ResultDescriptor;
import org.apache.commons.contract.descriptor.ResultEntryDescriptor;
import org.apache.commons.contract.descriptor.StateDescriptor;
import org.apache.commons.contract.i18n.ParameterMessage;
import org.apache.commons.i18n.LocalizedError;
import org.apache.commons.i18n.LocalizedMessage;
import org.apache.slide.projector.constraints.TextConstraints;
import org.apache.slide.projector.value.Streamable;
import org.apache.slide.projector.value.Text;

public class TemplateArrayRenderer extends TemplateRenderer {
    private static Logger logger = Logger.getLogger(TemplateArrayRenderer.class.getName());

    private ParameterDescriptor[] parameterDescriptors;

    public void configure(Streamable config) throws ConfigurationException {
        super.configure(config);
        parameterDescriptors = new ParameterDescriptor[parameterDescriptions.size()];
        int counter = 0;
        for ( Iterator i = parameterDescriptions.iterator(); i.hasNext(); ) {
            ParameterDescriptor entryDescriptor = (ParameterDescriptor)i.next();
            if ( entryDescriptor.getName() == FRAGMENT ) {
                parameterDescriptors[counter] = entryDescriptor;
            } else {
                parameterDescriptors[counter] = new ParameterDescriptor(entryDescriptor.getName(), new ParameterMessage("templateArrayRenderer/parameter"), new ArrayConstraints(entryDescriptor.getConstraints()));
            }
            counter++;
        }
    }

    public Result process(Map parameter, Context context) throws Exception {
        String fragment = ((Text)parameter.get(FRAGMENT)).toString();
        Template template = getRequiredFragment(fragment);
        parameter.remove(FRAGMENT);
        if ( template == null ) throw new ProcessException(new LocalizedError("templateArrayRenderer/fragmentNotFound", new String[] { fragment }));
        StringBuffer buffer = new StringBuffer(template.getLength());
        for ( int i = 0; i < getMaxIndex(parameter); i++ ) {
            template.evaluate(buffer, parameter, i);
        }
        return new Result(OK, OUTPUT, new Text(buffer.toString(), template.getContentType(), false));
    }

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

    public ResultDescriptor[] getResultDescriptors() {
        return new ResultDescriptor[] {new ResultDescriptor(
                StateDescriptor.OK_DESCRIPTOR,
                new ResultEntryDescriptor[]{
                    new ResultEntryDescriptor(OUTPUT, new LocalizedMessage("templateArrayRenderer/result/output"), 
                            TextConstraints.UNCONSTRAINED)
                })};
    }

    protected int getMaxIndex(Map parameter) {
        int maxIndex = 0;
        for ( Iterator i = parameter.values().iterator(); i.hasNext(); ) {
            Object[] value = (Object [])i.next();
            if ( value.length > maxIndex ) maxIndex = value.length;
        }
        return maxIndex;
    }
}