package org.seasar.struts.config;

import java.util.Collection;
import java.util.Iterator;

import org.apache.struts.config.FormBeanConfig;
import org.apache.struts.config.ModuleConfig;
import org.codehaus.backport175.reader.Annotation;
import org.codehaus.backport175.reader.Annotations;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;
import org.seasar.struts.config.rule.ZeroConfigActionFormRule;
import org.seasar.struts.form.NullStrutsActionForm;
import org.seasar.struts.form.StrutsActionForm;

/**
 * @author Katsuhiko Nagashima
 */
public class AutoActionFormRegister {

    private AutoActionFormRegister() {
    }

    public static void regist(ModuleConfig config, Collection classes) {
        classes = ClassComparator.sort(classes);
        
        for (Iterator iterator = classes.iterator(); iterator.hasNext();) {
            Class clazz = (Class) iterator.next();
            Annotation annotation = Annotations.getAnnotation(StrutsActionForm.class, clazz);
            StrutsActionForm strutsActionForm = null;
            if (annotation != null) {
                strutsActionForm = (StrutsActionForm) annotation;
            } else if (clazz.getName().matches(configRule().getFormClassPattern())) {
                strutsActionForm = new NullStrutsActionForm();
            }
            if (strutsActionForm != null) {
                registActionForm(strutsActionForm, clazz, config);
            }
        }
    }

    private static void registActionForm(StrutsActionForm form, Class formClass, ModuleConfig config) {
        String name = getName(form, formClass, config);
        if (config.findFormBeanConfig(name) == null) {
            regist(config, form, formClass);
        }
    }

    private static void regist(ModuleConfig config, StrutsActionForm form, Class formClass) {
        FormBeanConfig formBeanConfig = new FormBeanConfig();
        formBeanConfig.setName(getName(form, formClass, config));
        formBeanConfig.setType(formClass.getName());
        formBeanConfig.setRestricted(getRestricted(form, formClass, config));
        config.addFormBeanConfig(formBeanConfig);
    }

    private static ZeroConfigActionFormRule rule() {
        S2Container container = SingletonS2ContainerFactory.getContainer();
        return (ZeroConfigActionFormRule) container.getComponent(ZeroConfigActionFormRule.class);
    }

    private static AutoStrutsConfigRule configRule() {
        S2Container container = SingletonS2ContainerFactory.getContainer();
        return (AutoStrutsConfigRule) container.getComponent(AutoStrutsConfigRule.class);
    }

    private static String getName(StrutsActionForm form, Class formClass, ModuleConfig config) {
        return form.name() == StrutsActionForm.DEFAULT_NAME ? rule().getName(formClass, config) : form.name();
    }

    private static boolean getRestricted(StrutsActionForm form, Class formClass, ModuleConfig config) {
        return form.restricted() == StrutsActionForm.DEFAULT_RESTRICTED ? rule().getRestricted(formClass, config)
                : form.restricted();
    }

}
