/*
 * blancoIg
 * Copyright (C) 2004-2005 Yasuo Nakanishi
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 */
package blanco.struts.expander.form;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import blanco.core.datastruct.DataStructClass;
import blanco.core.datastruct.ReadAccessor;
import blanco.core.datastruct.WriteAccessor;
import blanco.ig.expander.Type;
import blanco.ig.expander.Value;
import blanco.ig.expander.field.FieldExpander;
import blanco.ig.expander.field.PrivateField;
import blanco.ig.expander.implementor.Call;
import blanco.ig.expander.implementor.StringLiteral;
import blanco.ig.expander.method.MethodExpander;
import blanco.struts.definition.form.Form;
import blanco.struts.definition.form.FormEvent;
import blanco.struts.definition.form.FormField;
import blanco.struts.definition.form.FormTable;
import blanco.struts.expander.TypeFactory;
import blanco.struts.generator.StrutsSetting;
import blanco.struts.metadata.StrutsMetadata;

/**
 * @author Yasuo Nakanishi
 */
public class ActionFormClass extends DataStructClass {

    private StrutsSetting _setting = null;

    private Form _form = null;

    private TypeFactory _typeFactory = null;

    private String _eventParameterName = "";

    private StrutsMetadata _metadata = null;

    private String _superClass = null;

    public ActionFormClass(StrutsSetting setting, StrutsMetadata metadata,
            Form form) {
        super(form.getType(), form);

        _setting = setting;
        _form = form;
        _typeFactory = new TypeFactory(_setting);

        _eventParameterName = metadata.getEventParameterName();
        _superClass = metadata.getFormSuperClass();
    }

    protected void expandClassStruct() {
        super.expandClassStruct();

        String name = getNameAdjuster().toValueName(_eventParameterName);
        Value eventId = new Value(String.class, name);

        FieldExpander field = new PrivateField(eventId);
        field.setDefaultStatement(new StringLiteral(""));
        addField(field);
        addMethod(new ReadAccessor(eventId));
        addMethod(new WriteAccessor(eventId));

        Type superClass = null;
        superClass = new Type(_superClass);
        MethodExpander method = null;

        setSuperClass(superClass);

        // Map‘Î‰ž
        // for (int index = 0; index < getFieldCount(); index++) {
        // field = getField(index);
        // if (field.getFieldValue().getType().equals(Map.class)) {
        // field.setDefaultValue(Hashtable.class);
        // }
        // }

        method = new ValidateMethod(_form, _typeFactory);
        addMethod(method);
        if (_form.isAutoValidation()) {
            expandAutoValidation();
        } else {
            expandEventValidation();
        }

        expandFormTable();

        Iterator i = _form.getFieldIterator();
        FormField f = null;
        Type type = null;
        while (i.hasNext()) {
            f = (FormField) i.next();
            type = f.getValue().getType();
            if (f.getUiType().equals("DropdownList")) {
                Value value = getOptionsCollectionValue(f);
                addField(createOptionsField(value));
                addMethod(new ReadAccessor(value));
                addMethod(new WriteAccessor(value));
            }
        }

        addMethod(new ResetMethod(_form));

        getJavaDoc().addLine(_form.getFormClassName());
        getJavaDoc().addLine(_form.getFormClassOutLine());
    }

    public static Value getOptionsCollectionValue(FormField field) {
        Type type = new Type(Collection.class);
        String name = field.getValue().getName() + "Options";
        return new Value(type, name);
    }

    private FieldExpander createOptionsField(Value value) {
        FieldExpander result = new PrivateField(value);
        result.setDefaultStatement(new Call(ArrayList.class));
        return result;
    }

    private void expandFormTable() {
        Iterator i = _form.getTableIterator();
        FormTable table = null;
        Value value = null;
        String name = "";
        FieldExpander f = null;
        while (i.hasNext()) {
            table = (FormTable) i.next();
            name = table.getId();

            addImport(new Type(List.class));
            addImport(new Type(ArrayList.class));

            value = new Value(new Type(List.class), name + "List");
            f = new PrivateField(value);
            f.setDefaultStatement(new Call(ArrayList.class));
            addField(f);
            addMethod(new ReadAccessor(value));
            addMethod(new WriteAccessor(value));
            addMethod(new GetListItemMethod(name, table.getType()));
        }
    }

    public static String createTableFieldName(FormTable table) {
        return table.getId() + "List";
    }

    private void expandAutoValidation() {
        MethodExpander method = null;
        method = new ValidateRequiredMethod(_form, _typeFactory);
        addMethod(method);
        method = new ValidateFormatMethod(_form, _typeFactory);
        addMethod(method);
        method = new ValidateRangeMethod(_form, _typeFactory);
        addMethod(method);
    }

    private void expandEventValidation() {
        Iterator i = _form.getEventIterator();
        FormEvent event = null;
        Iterator eventFields = null;
        Iterator tables = null;
        MethodExpander method = null;
        while (i.hasNext()) {
            event = (FormEvent) i.next();
            eventFields = _form.getEventFieldIterator(event.getName());
            tables = _form.getTableIterator();
            method = new ValidateRequiredEventMethod(event.getName(),
                    eventFields, tables, _typeFactory);
            addMethod(method);

            eventFields = _form.getEventFieldIterator(event.getName());
            tables = _form.getTableIterator();
            method = new ValidateFormatEventMethod(event.getName(),
                    eventFields, tables, _typeFactory);
            addMethod(method);
			
            eventFields = _form.getEventFieldIterator(event.getName());
            tables = _form.getTableIterator();
            method = new ValidateRangeEventMethod(event.getName(), eventFields,
                    tables, _typeFactory);
            addMethod(method);
        }
    }
}
