/*
 * Copyright (C) 2001-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.ui.authoring;


import com.arsdigita.bebop.ColumnPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SaveCancelSection;
import com.arsdigita.bebop.event.FormInitListener;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.form.TextField;
import com.arsdigita.bebop.parameters.NotNullValidationListener;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.cms.Article;
import com.arsdigita.cms.ImageAsset;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.util.GlobalizationUtil;

/**
 * A form for modifying a single image asset attached to the article.
 * This is just a convenience class; children should override
 * the addWidgets, init and process methods.
 */
public abstract class BasicImageForm extends Form
    implements FormInitListener, FormProcessListener {

    public static final String versionId = "$Id: //cms/dev/src/com/arsdigita/cms/ui/authoring/BasicImageForm.java#7 $ by $Author: dennis $, $DateTime: 2004/04/07 16:07:11 $";

    private ItemSelectionModel m_itemModel, m_assetModel;
    private SaveCancelSection m_saveCancelSection;

    public static final String CAPTION = "caption";

    /**
     * Construct a new BasicImageForm
     *
     * @param formName The name for this form
     *
     * @param itemModel The {@link ItemSelectionModel} which will
     *   be responsible for loading the current item
     *
     * @param assetModel The {@link ItemSelectionModel} which will
     *   be responsible for loading the current image asset
     */
    public BasicImageForm(String formName,
                          ItemSelectionModel itemModel, ItemSelectionModel assetModel
                          ) {
        super(formName, new ColumnPanel(2));
        m_itemModel = itemModel;
        m_assetModel = assetModel;

        ColumnPanel panel = (ColumnPanel)getPanel();
        panel.setBorder(false);
        panel.setPadColor("#FFFFFF");
        panel.setColumnWidth(1, "20%");
        panel.setColumnWidth(2, "80%");
        panel.setWidth("2%");

        addWidgets();

        m_saveCancelSection = new SaveCancelSection();
        add(m_saveCancelSection, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);

        addInitListener(this);
        addProcessListener(this);
    }

    /**
     * Add various widgets to the form. Child classes should override
     * this method to perform all their widget-adding needs
     */
    protected void addWidgets() {
        add(new Label(GlobalizationUtil.globalize("cms.ui.authoring.caption")));

        // WAI requires all images to maintain ALT attribute
        // aplaws ticket 14026
        StringParameter captionParam = new StringParameter(CAPTION);
        captionParam.addParameterListener(new NotNullValidationListener());
        TextField captionWidget = new TextField(captionParam);

        add(captionWidget);
    }

    /**
     * Perform form initialization. Children should override this
     * this method to pre-fill the widgets with data, instantiate
     * the content item, etc.
     */
    public abstract void init(FormSectionEvent e) throws FormProcessException;

    /**
     * Process the form. Children should override this method to save
     * the user's changes to the database.
     */
    public abstract void process(FormSectionEvent e) throws FormProcessException;

    /**
     * Helper method to pre-fill the "Caption" textbox. Should be called from
     * the init listener
     *
     * @param e The FormSectionEvent
     */
    public void initCaption(FormSectionEvent e) {
        FormData data = e.getFormData();
        PageState state = e.getPageState();

        Article item = getArticle(state);
        ImageAsset asset = getImageAsset(state);

        if(item != null && asset != null) {
            String caption = item.getCaption(asset);
            if(caption != null)
                data.put(CAPTION, caption);
        }
    }

    /**
     * Helper method to process "Caption" textbox. Should be called from
     * the process listener
     *
     * @param e The FormSectionEvent
     */
    public void processCaption(FormSectionEvent e) {
        FormData data = e.getFormData();
        PageState state = e.getPageState();

        Article item = getArticle(state);
        ImageAsset asset = getImageAsset(state);

        if(item != null && asset != null) {
            item.addImage(asset, (String)data.get(CAPTION));
        }
    }

    /**
     * @return the item selection model used in this form
     */
    public ItemSelectionModel getItemSelectionModel() {
        return m_itemModel;
    }

    /**
     * @return the asset selection model used in this form
     */
    public ItemSelectionModel getAssetSelectionModel() {
        return m_assetModel;
    }

    /**
     * @return the save/cancel section for this form
     */
    public SaveCancelSection getSaveCancelSection() {
        return m_saveCancelSection;
    }

    /**
     * @param state The page state
     * @return the currently selected item
     */
    public Article getArticle(PageState state) {
        return (Article)m_itemModel.getSelectedObject(state);
    }

    /**
     * @param state The page state
     * @return the currently selected image asset
     */
    public ImageAsset getImageAsset(PageState state) {
        return (ImageAsset)m_assetModel.getSelectedObject(state);
    }

    /**
     * Set the image asset. This will probably be done in the process
     * listener
     *
     * @param state The page state
     * @param asset The image asset
     */
    public void setImageAsset(PageState state, ImageAsset asset) {
        m_assetModel.setSelectedObject(state, asset);
        // Force the item to reload, since the assets query is cached ?
        // ?
    }

}
