/*
 * 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.cms.contenttypes.ui;

import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Resettable;
import com.arsdigita.bebop.SimpleContainer;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * A container which implements the {@link Resettable} interface and
 * provides other useful methods.
 *
 * @author <a href="mailto:phong@arsdigita.com">Phong Nguyen</a>
 * @version $Revision: #6 $
 **/
public class ResettableContainer extends SimpleContainer implements Resettable {

    // $Source: /cvsroot/content-types/apps/content-types/src/ui/ResettableContainer.java,v $
    // $Revision: #6 $
    // $Date: 2004/04/07 $
    // $Author: dennis $


    // A list of all resettable components in this container
    private ArrayList m_resettableComponents = new ArrayList();

    // A list of all components that are not visible by default
    private ArrayList m_componentsNotVisibleByDefault = new ArrayList();


    /**
     * Constructs a new, empty <code>RessetableContainer</code>.
     **/
    public ResettableContainer() {
        super();
    }

    /**
     * Constructs a new, empty <code>RessetableContainer</code>.
     *
     * @param key The key for this container.
     **/
    public ResettableContainer(String key) {
        super();
        setKey(key);
    }

    /**
     * Constructs a new, empty <code>RessetableContainer</code>. The
     * container will wrap its children in the specified tag.
     *
     * @param tag The name of the XML element that will be used to
     * wrap the children of this container.
     * @param ns The namespace for the tag.
     **/
    public ResettableContainer(String tag, String ns) {
        super(tag, ns);
    }

    /**
     * Adds a component to container.
     *
     * @param pc The component to be added.
     * @pre (pc != null)
     * @post (m_components.contains(pc))
     **/
    public void add(Component pc) {
        add(pc, true);
    }

    /**
     * Add a component to this container
     *
     * @param pc The component to be added.
     * @param constraints This parameter is ignored. Child classes
     * should override the add method if they wish to provide special
     * handling of constraints.
     **/
    public void add(Component pc, int constraints) {
        add(pc);
    }

    /**
     * Adds the component to this pane with the specified default
     * visibility.
     *
     * @param defaultVisibility The default visibility of this component
     * @pre (pc != null)
     **/
    public void add(Component pc, boolean defaultVisibility) {
        super.add(pc);
        if (pc instanceof Resettable) {
            m_resettableComponents.add(pc);
        }
        if (! defaultVisibility) {
            m_componentsNotVisibleByDefault.add(pc);
        }
    }

    /**
     * Sets the visibility of all child components to false, except
     * for the component with the specified key.
     *
     * @param state The state of the current request.
     * @param key The key of the component. There will be no
     * visibility changes if key is null.
     **/
    public void onlyShowComponent(PageState state, String key) {
        if (key == null) { return; }

        Component child;
        Iterator iter = children();
        while (iter.hasNext()) {
            child = (Component) iter.next();
            child.setVisible(state, key.equals(child.getKey()));
        }
    }

    /**
     * Sets the visibility of all child components to false, except
     * for the specified component.
     *
     * @param state The state of the current request.
     * @param c The key of the component. There will be no visibility
     * changes if <code>c</code> is null.
     **/
    public void onlyShowComponent(PageState state, Component c) {
        if (c == null) { return; }

        Component child;
        Iterator iter = children();
        while (iter.hasNext()) {
            child = (Component) iter.next();
            child.setVisible(state, child.equals(c));
        }
    }

    /**
     * Resets all resettable components added to this container.
     *
     * @param state The state of the current request.
     **/
    public void reset(PageState state) {
        // Reset all resettable components automatically
        Iterator iter = m_resettableComponents.iterator();
        while (iter.hasNext()) {
            ((Resettable) iter.next()).reset(state);
        }
    }

    /**
     * Registers with page that this container belongs to and sets the
     * default visibility of child components.
     *
     * @param p The page this container belongs to.
     **/
    public void register(Page p) {
        Iterator iter = m_componentsNotVisibleByDefault.iterator();
        while (iter.hasNext()) {
            p.setVisibleDefault((Component) iter.next(), false);
        }
    }

}
