/*
 * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the
 * License at http://www.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.formbuilder.ui;


import com.arsdigita.formbuilder.MetaObject;
import com.arsdigita.formbuilder.MetaObjectCollection;
import java.math.BigDecimal;
import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.util.UncheckedWrapperException;
import java.util.HashMap;
import java.util.Iterator;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.event.FormSubmissionListener;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.event.FormSectionEvent;



public abstract class MetaObjectProperties extends SimpleContainer {
    private HashMap m_widget_map;
    private HashMap m_id_map;
    private String m_app;
    private Class m_type;

    public MetaObjectProperties(String app,
                                Class type) {
        m_type = type;
        m_app = app;

        m_widget_map = new HashMap();
        m_id_map = new HashMap();
    }

    protected void addForms() {
        MetaObjectCollection forms = null;
        try {
            forms = MetaObject.getWidgets(m_app, m_type);
        } catch (DataObjectNotFoundException ex) {
            throw new UncheckedWrapperException("cannot find object type", ex);
        }
        while (forms.next()) {
            MetaObject obj = forms.getMetaObject();
            PropertiesEditor f = getPropertiesEditor(obj);
            f.setApplication(m_app);

            m_widget_map.put(obj.getWidgetClassName(), f);
            m_id_map.put(obj.getID(), f);
            add(f);
        }
    }

    public void register(Page p) {
        super.register(p);

        Iterator forms = m_widget_map.values().iterator();
        while (forms.hasNext()) {
            PropertiesEditor f = (PropertiesEditor)forms.next();
            p.setVisibleDefault(f, false);
        }
    }

    public void setFormVisible(PageState state,
                               String widget) {

        Iterator forms = m_widget_map.keySet().iterator();
        while (forms.hasNext()) {
            String className = (String)forms.next();
            PropertiesEditor f = (PropertiesEditor)m_widget_map.get(className);
            f.setVisible(state, className.equals(widget));
        }
    }

    public void setFormVisible(PageState state,
                               BigDecimal widget) {
        Iterator forms = m_id_map.keySet().iterator();
        while (forms.hasNext()) {
            BigDecimal id = (BigDecimal)forms.next();
            PropertiesEditor f = (PropertiesEditor)m_id_map.get(id);
            f.setVisible(state, id.equals(widget));
        }
    }


    public void addCompletionListener(FormCompletionListener l) {
        Iterator forms = m_widget_map.values().iterator();
        while (forms.hasNext()) {
            PropertiesEditor f = (PropertiesEditor)forms.next();

            MetaObjectListener ml = new MetaObjectListener(l, this);

            f.addProcessListener(ml);
            f.addSubmissionListener(ml);
        }
    }

    private class MetaObjectListener implements FormSubmissionListener, FormProcessListener {
        FormCompletionListener m_l;
        Object m_source;

        public MetaObjectListener(FormCompletionListener l,
                                  Object source) {
            m_l = l;
            m_source = source;
        }

        public void process(FormSectionEvent e)
            throws FormProcessException {

            PropertiesEditor f = (PropertiesEditor)e.getSource();

            if (f.isComplete(e.getPageState())) {
                m_l.complete(new FormSectionEvent(m_source,
                                                  e.getPageState(),
                                                  e.getFormData()));
            }
        }

        public void submitted(FormSectionEvent e)
            throws FormProcessException {

            PropertiesEditor f = (PropertiesEditor)e.getSource();

            if (f.isCancelled(e.getPageState())) {
                m_l.complete(new FormSectionEvent(m_source,
                                                  e.getPageState(),
                                                  e.getFormData()));
            }
        }
    }

    protected abstract PropertiesEditor getPropertiesEditor(MetaObject obj);
}
