/*
 * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
 *
 * 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.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */
package com.arsdigita.cms.ui;


import com.arsdigita.bebop.ColumnPanel;
import com.arsdigita.bebop.Container;
import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.FormSection;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.form.FileUpload;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.cms.util.GlobalizationUtil;
import com.arsdigita.globalization.GlobalizedMessage;  // this can be removed when the deprecated messages are removed.
import com.arsdigita.dispatcher.MultipartHttpServletRequest;
import com.arsdigita.mimetypes.MimeType;
import com.arsdigita.mimetypes.MimeTypeCollection;
import java.io.File;

/**
 * A form section with two widgets: a mime-type selection widget
 * and a file upload widget. The section will attempt to automatically
 * guess the mime type from the filename (if necessary), and
 * return the mime type.
 *
 * @author Stanislav Freidin (sfreidin@arsdigita.com)
 * @version $Id: FileUploadSection.java 287 2005-02-22 00:29:02Z sskracic $
 */
public class FileUploadSection extends FormSection {

    public static final String versionId = "$Id: FileUploadSection.java 287 2005-02-22 00:29:02Z sskracic $ by $Author: sskracic $, $DateTime: 2004/08/17 23:15:09 $";

    private SingleSelect m_mimeWidget;
    private FileUpload m_fileWidget;
    private String m_mimePrefix;
    private String m_defaultMimeType;
    private String m_parameterPrefix;

    /**
     * The mime type widget
     */
    public static final String MIME_TYPE = "mime_type";

    /**
     * The file upload widget
     */
    public static final String FILE_UPLOAD = "file_upload";

    /**
     * Automatically guess the mime type
     */
    public static final String GUESS_MIME = "-guess-";

    /**
     * Construct a new FileUploadSection
     *
     * @param mimeLabel The label for the mime type widget
     *
     * @param mimePrefix Populate the mime type widget with all
     *   mime types that match the prefix. Some of the possible
     *   prefixes are "text", "image", "binary", etc.
     *
     * @param defaultMimeType The default mime type that should be
     *   assumed if the guessing fails
     *
     * @param panel The panel that is to be used to lay out the
     *   components
     *
     */
    public FileUploadSection(
                             GlobalizedMessage mimeLabel, String mimePrefix, String defaultMimeType, Container panel
                             ) {
        this(mimeLabel, mimePrefix, defaultMimeType, "", panel);
    }


    /**
     * Construct a new FileUploadSection
     *
     * @param mimeLabel The label for the mime type widget
     *
     * @param mimePrefix Populate the mime type widget with all
     *   mime types that match the prefix. Some of the possible
     *   prefixes are "text", "image", "binary", etc.
     *
     * @param defaultMimeType The default mime type that should be
     *   assumed if the guessing fails
     *
     * @param panel The panel that is to be used to lay out the
     *   components
     *
     * @deprecated use the same constructor but with the GlobalizedMessage
     *             for the mimeLabel
     */
    public FileUploadSection(String mimeLabel, String mimePrefix, String defaultMimeType, Container panel) {
        // This takes advantage of the fact that the "key" is returned
        // when it is not present in the message bundle
        this(new GlobalizedMessage(mimeLabel), mimePrefix, defaultMimeType, panel);
    }

    /**
     * Construct a new FileUploadSection
     *
     * @param mimeLabel The label for the mime type widget
     *
     * @param mimePrefix Populate the mime type widget with all
     *   mime types that match the prefix. Some of the possible
     *   prefixes are "text", "image", "binary", etc.
     *
     * @param defaultMimeType The default mime type that should be
     *   assumed if the guessing fails
     *
     * @param parameterPrefix Prepended to MIME_TYPE and FILE_UPLOAD for
     * parameter names so that more than 1 file upload widgets may be
     * used per form
     *
     * @param panel The panel that is to be used to lay out the
     *   components
     *
     * @deprecated use the same constructor but with the GlobalizedMessage
     *             for the mimeLabel
     */
    public FileUploadSection(
                             String mimeLabel,
                             String mimePrefix,
                             String defaultMimeType,
                             String parameterPrefix,
                             Container panel
                             ) {
        // This takes advantage of the fact that the "key" is returned
        // when it is not present in the message bundle
        this(new GlobalizedMessage(mimeLabel), mimePrefix,
             defaultMimeType, parameterPrefix, panel);
    }


    /**
     * Construct a new FileUploadSection
     *
     * @param mimeLabel The label for the mime type widget
     *
     * @param mimePrefix Populate the mime type widget with all
     *   mime types that match the prefix. Some of the possible
     *   prefixes are "text", "image", "binary", etc.
     *
     * @param defaultMimeType The default mime type that should be
     *   assumed if the guessing fails
     *
     * @param parameterPrefix Prepended to MIME_TYPE and FILE_UPLOAD for
     * parameter names so that more than 1 file upload widgets may be
     * used per form
     *
     * @param panel The panel that is to be used to lay out the
     *   components
     *
     */
    public FileUploadSection(GlobalizedMessage mimeLabel,
                             String mimePrefix,
                             String defaultMimeType,
                             String parameterPrefix,
                             Container panel) {
        super(panel);

        m_mimePrefix = mimePrefix;
        m_defaultMimeType = defaultMimeType;
        if (parameterPrefix != null) {
            m_parameterPrefix = parameterPrefix;
        } else {
            m_parameterPrefix = "";
        }

        add(new Label(mimeLabel, false));
        m_mimeWidget = new SingleSelect(getMimeTypeWidgetName());
        addMimeOptions(m_mimeWidget, mimePrefix);
        m_mimeWidget.addOption(new Option(GUESS_MIME, new Label(GlobalizationUtil.globalize("cms.ui.authoring.file_upload.auto_detect"))));

        m_mimeWidget.setDefaultValue(GUESS_MIME);
        add(m_mimeWidget);

        add(new Label(GlobalizationUtil.globalize("cms.ui.upload_new_content")));
        m_fileWidget = new FileUpload(getFileUploadWidgetName());
        add(m_fileWidget);
    }

    /**
     * Construct a new FileUploadSection
     *
     * @param mimeLabel The label for the mime type widget
     *
     * @param mimePrefix Populate the mime type widget with all
     *   mime types that match the prefix. Some of the possible
     *   prefixes are "text", "image", "binary", etc.
     *
     * @param defaultMimeType The default mime type that should be
     *   assumed if the guessing fails
     *
     * @param parameterPrefix Prepended to MIME_TYPE and FILE_UPLOAD for
     * parameter names so that more than 1 file upload widgets may be
     * used per form
     *
     */
    public FileUploadSection (GlobalizedMessage mimeLabel,
                              String mimePrefix,
                              String defaultMimeType,
                              String parameterPrefix) {
        this(mimeLabel,
             mimePrefix,
             defaultMimeType,
             parameterPrefix,
             new ColumnPanel(2, true));
        ColumnPanel panel = (ColumnPanel)getPanel();
        panel.setBorder(false);
        panel.setPadColor("#FFFFFF");
    }


    /**
     * Construct a new FileUploadSection
     *
     * @param mimeLabel The label for the mime type widget
     *
     * @param mimePrefix Populate the mime type widget with all
     *   mime types that match the prefix. Some of the possible
     *   prefixes are "text", "image", "binary", etc.
     *
     * @param defaultMimeType The default mime type that should be
     *   assumed if the guessing fails
     *
     * @param parameterPrefix Prepended to MIME_TYPE and FILE_UPLOAD for
     * parameter names so that more than 1 file upload widgets may be
     * used per form
     *
     * @deprecated use the same constructor but with the GlobalizedMessage
     *             for the mimeLabel
     */
    public FileUploadSection (
                              String mimeLabel,
                              String mimePrefix,
                              String defaultMimeType,
                              String parameterPrefix
                              ) {
        // This takes advantage of the fact that the "key" is returned
        // when it is not present in the message bundle
        this(new GlobalizedMessage(mimeLabel),
             mimePrefix,
             defaultMimeType,
             parameterPrefix);
    }

    /**
     * Construct a new FileUploadSection
     *
     * @param mimeLabel The label for the mime type widget
     *
     * @param mimePrefix Populate the mime type widget with all
     *   mime types that match the prefix. Some of the possible
     *   prefixes are "text", "image", "binary", etc.
     *
     * @param defaultMimeType The default mime type that should be
     *   assumed if the guessing fails
     *
     * @deprecated use the same constructor but with the GlobalizedMessage
     *             for the mimeLabel
     */
    public FileUploadSection(
                             String mimeLabel, String mimePrefix, String defaultMimeType
                             ) {
        // This takes advantage of the fact that the "key" is returned
        // when it is not present in the message bundle
        this(new GlobalizedMessage(mimeLabel), mimePrefix, defaultMimeType, "");
    }

    /**
     * Construct a new FileUploadSection
     *
     * @param mimeLabel The GlobalizedMessage for the label for the mime 
     *                  type widget
     *
     * @param mimePrefix Populate the mime type widget with all
     *   mime types that match the prefix. Some of the possible
     *   prefixes are "text", "image", "binary", etc.
     *
     * @param defaultMimeType The default mime type that should be
     *   assumed if the guessing fails
     *
     */
    public FileUploadSection(GlobalizedMessage mimeLabel, String mimePrefix, 
                             String defaultMimeType) {
        this(mimeLabel, mimePrefix, defaultMimeType, "");
    }

    /**
     * Try to guess the mime type from the filename, and return
     * it. The parent form should call this method in its process
     * listener. Note that this method may return null if the mime
     * type could not be guessed.
     *
     * @param e The form section event
     */
    public MimeType getMimeType(FormSectionEvent e) {
        FormData data = e.getFormData();

        String fileName = (String)data.get(getFileUploadWidgetName());
        String mimeTypeName = (String)data.get(getMimeTypeWidgetName());
        MimeType mimeType = null;

        // Guess the mime type from the filename
        if(fileName != null) {
            if(GUESS_MIME.equals(mimeTypeName)) {
                // Guess the mime type from the file extension
                mimeType = MimeType.guessMimeTypeFromFile(fileName);
            } else {
                mimeType = MimeType.loadMimeType(mimeTypeName);
            }
        }

        // Failed to guess it, failed to load it, fall back on the default
        if(mimeType == null) {
            mimeType = MimeType.loadMimeType(m_defaultMimeType);
        }

        return mimeType;
    }

    /**
     * Obtain a File object from the file upload widget. The containing form
     * should call this method in its process listener.
     *
     * @param e The form section event
     */
    public File getFile(FormSectionEvent e) {
        FormData data = e.getFormData();
        String fileName = getFileName(e);

        if(fileName != null && fileName.length() > 0) {
            return ((MultipartHttpServletRequest)e.getPageState().getRequest())
                .getFile(getFileUploadWidgetName());
        }

        return null;
    }

    /**
     * Obtain a filename from the file upload widget. The containing form
     * should call this method in its process listener.
     *
     * @param e The form section event
     */
    public String getFileName(FormSectionEvent e) {
        FormData data = e.getFormData();
        return (String)data.get(getFileUploadWidgetName());
    }

    /**
     * Set the value for the mime type widget. The containing form should
     * call this method in its init listener
     *
     * @param e The form section event
     * @param mimeType The mime type to set, such as "textr/html" or "img/jpeg"
     *
     */
    public void setMimeType(FormSectionEvent e, String mimeType) {
        FormData data = e.getFormData();
        data.put(getMimeTypeWidgetName(), mimeType);
    }

    /**
     * @return the mime type widget
     */
    public SingleSelect getMimeTypeWidget() {
        return m_mimeWidget;
    }

    /**
     * @return the file upload widget
     */
    public FileUpload getFileUploadWidget() {
        return m_fileWidget;
    }

    /**
     * @return the parameter name prefix
     */
    public String getParameterPrefix() {
        return m_parameterPrefix;
    }

    /**
     * @return the file upload parameter name
     */
    public String getFileUploadWidgetName() {
        return m_parameterPrefix + FILE_UPLOAD;
    }

    /**
     * @return the mime typeparameter name
     */
    public String getMimeTypeWidgetName() {
        return m_parameterPrefix + MIME_TYPE;
    }

    /**
     * Add mime-type options to the option group by loading all mime
     * types which match a certain prefix from the database
     *
     * @param w The mime type widget to which options should be added
     *
     * @param mimePrefix Populate the mime type widget with all
     *   mime types that match the prefix. Some of the possible
     *   prefixes are "text", "image", "binary", etc.
     *
     */
    public static void addMimeOptions(OptionGroup w, String mimePrefix) {
        MimeTypeCollection types;
        if (mimePrefix == null || mimePrefix.equals("")) {
            types = MimeType.getAllMimeTypes();
        } else {
            types = MimeType.searchMimeTypes(mimePrefix + "/");
        }
        while(types.next()) {
            MimeType type = types.getMimeType();
            w.addOption(new Option(type.getMimeType(), type.getLabel()));
        }
    }

}
