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

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;

import org.apache.commons.contract.Context;
import org.apache.commons.contract.constraints.LocaleConstraints;
import org.apache.commons.contract.constraints.StringConstraints;
import org.apache.commons.contract.descriptor.ParameterDescriptor;
import org.apache.commons.contract.descriptor.ResultEntryDescriptor;
import org.apache.commons.contract.i18n.ParameterMessage;
import org.apache.commons.i18n.LocalizedMessage;
import org.apache.slide.projector.processor.SimpleProcessor;

/**
 * @version $Revision: 1.5 $
 */
public class LocaleResolver extends SimpleProcessor {
    private final static ParameterDescriptor parameterDescriptor = new ParameterDescriptor(INPUT, new ParameterMessage("localeResolver/locale"), StringConstraints.UNCONSTRAINED, new String(Locale.getDefault().toString()));
    private final static ResultEntryDescriptor resultEntryDescriptor =  new ResultEntryDescriptor(SimpleProcessor.OUTPUT, new LocalizedMessage("locale/result/output"), LocaleConstraints.UNCONSTRAINED);

    public Object process(Object input, Context context) throws Exception {
        List acceptedLanguages = new ArrayList();
        StringTokenizer tokenizer = new StringTokenizer((String)input, ",");
        while ( tokenizer.hasMoreTokens() ) {
            String localeToken = tokenizer.nextToken();
            double q = 1.0;
            int qIndex = localeToken.indexOf(";q=");
            if ( qIndex > 0 ) {
                q = Double.parseDouble(localeToken.substring(qIndex+3));
                localeToken = localeToken.substring(0, qIndex);
            }
            // FIXME: Only add values that are supported by the current webapp (configure globally)
            acceptedLanguages.add(new AcceptedLanguage(q, new Locale(localeToken)));
        }
        Collections.sort(acceptedLanguages);
        return ((AcceptedLanguage)acceptedLanguages.get(0)).getLocale();
    }

    public ParameterDescriptor getParameterDescriptor() {
        return parameterDescriptor;
    }

    public ResultEntryDescriptor getResultEntryDescriptor() {
        return resultEntryDescriptor;
    }

    class AcceptedLanguage implements Comparable {
        double q;
        Locale locale;

        public AcceptedLanguage(double q, Locale locale) {
            this.q = q;
            this.locale = locale;
        }

        public Locale getLocale() {
            return locale;
        }

        public double getQ() {
            return q;
        }

        public int compareTo(Object a) {
            if ( ((AcceptedLanguage)a).getQ() < q ) return -1;
            if ( ((AcceptedLanguage)a).getQ() > q ) return 1;
            return 0;
        }
    }
}