/*
 * 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.util.GlobalizationUtil ; 


import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Form;


import com.arsdigita.formbuilder.util.FormBuilderUtil;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.MetaForm;
import java.math.BigDecimal;
import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.formbuilder.PersistentComponentFactory;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ColumnPanel;
import com.arsdigita.bebop.FormSection;
import com.arsdigita.bebop.GridPanel;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;

import com.arsdigita.formbuilder.PersistentFormSection;
import com.arsdigita.formbuilder.util.FormBuilderUtil;
import com.arsdigita.formbuilder.PersistentForm;
import com.arsdigita.formbuilder.ui.BaseAddObserver;
import java.util.ArrayList;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.formbuilder.PersistentWidget;
import com.arsdigita.formbuilder.WidgetLabel;
import java.util.Iterator;
import com.arsdigita.formbuilder.PersistentComponent;
import java.util.HashSet;


public class MoveControl extends MetaForm {
    private SingleSelectionModel m_form;
    private SingleSelectionModel m_control;

    private ArrayList m_listeners;

    public MoveControl(SingleSelectionModel form,
                       SingleSelectionModel control) {
        super("view_form");

        m_form = form;
        m_control = control;

        m_listeners = new ArrayList();

        addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    PageState state = e.getPageState();

                    String name = state.getControlEventName();
                    String value = state.getControlEventValue();

                    if (name.equals("move")) {
                        Integer pos = new Integer(value);
                        BigDecimal control_id = (BigDecimal)m_control.getSelectedKey(state);
                        BigDecimal form_id = (BigDecimal)m_form.getSelectedKey(state);

                        PersistentFormSection form = (PersistentFormSection)FormBuilderUtil.instantiateObject(form_id);
                        PersistentComponent control = (PersistentComponent)FormBuilderUtil.instantiateObject(control_id);

                        WidgetLabel label = null;

                        if (control instanceof PersistentWidget) {
                            try {
                                label = WidgetLabel.findByWidget((PersistentWidget)control);
                            } catch (DataObjectNotFoundException ex) {
                                // Nada
                            }
                        }

                        if (label != null)
                            form.removeComponent(label);
                        form.removeComponent(control);
                        if (label != null)
                            form.addComponent(label, pos.intValue());
                        form.addComponent(control, (label == null ? pos.intValue() : pos.intValue() + 1));
                        //form.moveComponent(label, pos.intValue());
                        //form.moveComponent(control, pos.intValue()+1);
                    }
                }
            });

    }

    public Form buildForm(PageState state) {
        BigDecimal form_id = (BigDecimal)m_form.getSelectedKey(state);
        BigDecimal control_id = (BigDecimal)m_control.getSelectedKey(state);
        PersistentFormSection section = (PersistentFormSection)FormBuilderUtil.instantiateObject(form_id);

        section.setComponentAddObserver(new MoveControlObserver(this, control_id));

        try {
            PersistentForm form = (PersistentForm)section;
            return (Form)form.createComponent();
        } catch (ClassCastException ex) {
            Form form = new Form("view_form", new ColumnPanel(1));//, new BoxPanel(BoxPanel.HORIZONTAL));
            form.add((FormSection)section.createComponent());
            return form;
        }
    }

    public void addActionListener(ActionListener l) {
        m_listeners.add(l);
    }

    public void fireActionEvent(ActionEvent e) {
        Iterator listeners = m_listeners.iterator();
        while (listeners.hasNext()) {
            ActionListener l = (ActionListener)listeners.next();

            l.actionPerformed(e);
        }
    }

    public void respond(PageState state)
        throws javax.servlet.ServletException {
        super.respond(state);

        fireActionEvent(new ActionEvent(this, state));
    }


    private class MoveControlObserver extends BaseAddObserver {
        Component m_handler;
        boolean m_before;
        boolean m_after;
        BigDecimal m_moving;
        HashSet m_seen;

        public MoveControlObserver(Component handler,
                                   BigDecimal moving) {
            m_handler = handler;
            m_before = true;
            m_after = false;
            m_moving = moving;
            m_seen = new HashSet();
        }

        public void beforeAddingComponent(FormSection formSection,
                                          PersistentComponentFactory componentFactory,
                                          int componentPosition) {
            super.beforeAddingComponent(formSection,
                                        componentFactory,
                                        componentPosition);

            if (componentFactory.getID().equals(m_moving))
                m_before = false;

            if (componentFactory instanceof WidgetLabel) {
                WidgetLabel label = (WidgetLabel)componentFactory;
                BigDecimal id = label.getWidgetID();
                m_seen.add(id);

                if (id.equals(m_moving)) {
                    addLabel(formSection);
                    m_seen.add(componentFactory.getID());
                }
            }

            if (!m_seen.contains(componentFactory.getID()) &&
                m_before)
                addLink(formSection, componentPosition);

        }

        public void addingComponent(PersistentComponentFactory componentFactory,
                                    int componentPosition,
                                    Component component) {
            super.addingComponent(componentFactory,
                                  componentPosition,
                                  component);
        }

        public void afterAddingComponent(FormSection formSection,
                                         PersistentComponentFactory componentFactory,
                                         int componentPosition) {
            super.afterAddingComponent(formSection,
                                       componentFactory,
                                       componentPosition);

            if (!(componentFactory instanceof WidgetLabel) &&
                m_after) {
                addLink(formSection, componentPosition-1);
            }

            if (componentFactory.getID().equals(m_moving)) {
                m_after = true;
                addLabel(formSection);
            }
        }

        protected void addLabel(FormSection form) {
            Label l = new Label(GlobalizationUtil.globalize("formbuilder.ui.move_it_here"));
            form.add(l, GridPanel.FULL_WIDTH);
        }

        protected void addLink(FormSection form,
                               int row) {
            ControlLink l = new MoveLink("[move it here]", row);
            form.add(l, GridPanel.FULL_WIDTH);
        }

        private class MoveLink extends ControlLink {
            int m_row;

            public MoveLink(String name,
                            int row) {
                super(name);
                m_row = row;
            }

            public void setControlEvent(PageState state) {
                state.setControlEvent(m_handler, "move", (new Integer(m_row)).toString());
            }
        }
    }
}
