/*
 * Copyright (C) 2003-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;

import com.arsdigita.bebop.form.DHTMLEditor;
import com.arsdigita.bebop.SimpleComponent;
import com.arsdigita.cms.dispatcher.DefaultTemplateResolver;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.dispatcher.MultilingualItemResolver;
import com.arsdigita.cms.dispatcher.TemplateResolver;
import com.arsdigita.cms.publishToFile.PublishToFile;
import com.arsdigita.cms.publishToFile.PublishToFileListener;
import com.arsdigita.cms.ui.authoring.ItemCategoryForm;
import com.arsdigita.runtime.AbstractConfig;
import com.arsdigita.util.parameter.BooleanParameter;
import com.arsdigita.util.parameter.ErrorList;
import com.arsdigita.util.parameter.IntegerParameter;
import com.arsdigita.util.parameter.Parameter;
import com.arsdigita.util.parameter.ParameterError;
import com.arsdigita.util.parameter.ClassParameter;
import com.arsdigita.util.parameter.StringParameter;
import com.arsdigita.util.parameter.StringArrayParameter;
import com.arsdigita.util.parameter.URLParameter;
import com.arsdigita.util.UncheckedWrapperException;

import org.apache.log4j.Logger;

import java.io.InputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * A record containing server-session scoped configuration properties.
 *
 * Accessors of this class may return null.  Developers should take
 * care to trap null return values in their code.
 *
 * @see ContentSection#getConfig()
 *
 * @author Justin Ross &lt;jross@redhat.com&gt;
 * @version $Id: //cms/dev/src/com/arsdigita/cms/ContentSectionConfig.java#12 $
 */
public final class ContentSectionConfig extends AbstractConfig {
    public static final String versionId =
        "$Id: //cms/dev/src/com/arsdigita/cms/ContentSectionConfig.java#12 $" +
        "$Author: dennis $" +
        "$DateTime: 2004/04/07 16:07:11 $";

    private static final Logger s_log = Logger.getLogger(ContentSectionConfig.class);

    private final Parameter m_templateRootPath;
    private final Parameter m_defaultItemTemplatePath;
    private final Parameter m_defaultFolderTemplatePath;
    private final Parameter m_languages;
    private final Parameter m_publishToFileClass;
    private final Parameter m_disableItemPfs;
    private final Parameter m_defaultItemResolverClass;
    private final Parameter m_defaultTemplateResolverClass;
    private final Parameter m_categoryAuthoringAddForm;
    private final Parameter m_useSectionCategories;
    private final Parameter m_itemAdapters;
    private final Parameter m_defaultSection;
    private final Parameter m_useStreamlinedCreation;
    private final Parameter m_dhtmlEditorConfig;
    private final Parameter m_dhtmlEditorPlugins;
    private final Parameter m_hideTemplatesTab;
    private final Parameter m_hideAdminTabs;
    private final Parameter m_hideTimezone;
    private final Parameter m_hideLaunchDate;
    private final Parameter m_hideUDCTUI;
    private final Parameter m_hideFolderIndexCheckbox;
    private final Parameter m_defaultNotificationTime;

    /**
     * Do not instantiate this class directly.
     *
     * @see ContentSection#getConfig()
     **/
    public ContentSectionConfig() {
        m_templateRootPath = new StringParameter
            ("com.arsdigita.cms.template_root_path",
             Parameter.REQUIRED, "/packages/content-section/templates");
        m_defaultItemTemplatePath = new StringParameter
            ("com.arsdigita.cms.default_item_template_path",
             Parameter.REQUIRED, "/default/item.jsp");
        m_defaultFolderTemplatePath = new StringParameter
            ("com.arsdigita.cms.default_folder_template_path",
             Parameter.REQUIRED, "/default/folder.jsp");
        m_languages = new StringParameter
            ("com.arsdigita.cms.languages",
             Parameter.REQUIRED, "en,de,fr,nl,it,pt,es");
        m_publishToFileClass = new SpecificClassParameter
            ("com.arsdigita.cms.publish_to_file_class",
             Parameter.REQUIRED,
             PublishToFile.class,
             PublishToFileListener.class);

        // XXX these are probably temporary parameters, as the
        // item/template resolvers will be determined by the successor
        // to SectionInitializer. However, it still may be useful to
        // keep these for the default values.
        m_defaultItemResolverClass = new SpecificClassParameter
            ("com.arsdigita.cms.default_item_resolver_class",
             Parameter.REQUIRED,
             MultilingualItemResolver.class,
             ItemResolver.class);
        m_defaultTemplateResolverClass = new SpecificClassParameter
            ("com.arsdigita.cms.default_template_resolver_class",
             Parameter.REQUIRED,
             DefaultTemplateResolver.class,
             TemplateResolver.class);

        m_categoryAuthoringAddForm = new SpecificClassParameter
            ("com.arsdigita.cms.category_authoring_add_form",
             Parameter.REQUIRED,
             ItemCategoryForm.class,
             SimpleComponent.class);

        // XXX: temporary parameter. will be removed when MapParameter
        // works and the p2fs initializer is converted away from the
        // legacy init
        m_disableItemPfs = new BooleanParameter
            ("com.arsdigita.cms.disable_item_pfs",
             Parameter.REQUIRED, new Boolean(false));

        // XXX: temporary parameter. will be removed when
        // SectionInitializer is replaced with a separate Section
        // loader app.
        m_useSectionCategories = new BooleanParameter
            ("com.arsdigita.cms.use_section_categories",
             Parameter.REQUIRED, new Boolean(true));

        try {
            m_itemAdapters = new URLParameter
                ("com.arsdigita.cms.item_adapters",
                 Parameter.REQUIRED,
                 new URL("resource:///WEB-INF/resources/cms-item-adapters.xml"));
        } catch (MalformedURLException ex) {
            throw new UncheckedWrapperException("Cannot parse URL", ex);
        }

        m_defaultSection = new StringParameter
            ("com.arsdigita.cms.default_content_section",
             Parameter.REQUIRED, "content");

        m_useStreamlinedCreation = new BooleanParameter
            ("com.arsdigita.cms.use_streamlined_creation",
             Parameter.REQUIRED, new Boolean(false));

        m_dhtmlEditorConfig = new DHTMLEditorConfigParameter
            ("com.arsdigita.cms.dhtml_editor_config",
             Parameter.REQUIRED, 
             DHTMLEditor.Config.STANDARD);

        m_dhtmlEditorPlugins = new StringArrayParameter
            ("com.arsdigita.cms.dhtml_editor_plugins",
             Parameter.OPTIONAL,
             null);

        m_hideTemplatesTab = new BooleanParameter
            ("com.arsdigita.cms.hide_templates_tab",
             Parameter.REQUIRED, new Boolean(false));

        m_hideAdminTabs = new BooleanParameter
            ("com.arsdigita.cms.hide_admin_tabs",
             Parameter.REQUIRED, new Boolean(false));

        m_hideTimezone = new BooleanParameter
            ("com.arsdigita.cms.hide_timezone",
             Parameter.REQUIRED, new Boolean(false));

        m_hideLaunchDate = new BooleanParameter
            ("com.arsdigita.cms.hide_launch_date",
             Parameter.REQUIRED, new Boolean(true));

        m_hideUDCTUI = new BooleanParameter
            ("com.arsdigita.cms.hide_udct_ui",
             Parameter.REQUIRED, new Boolean(false));

        m_hideFolderIndexCheckbox = new BooleanParameter
            ("com.arsdigita.cms.hide_folder_index_checkbox",
             Parameter.REQUIRED, new Boolean(false));

        m_defaultNotificationTime = new IntegerParameter
            ("com.arsdigita.cms.default_notification_time",
             Parameter.REQUIRED, new Integer(0));


        register(m_templateRootPath);
        register(m_defaultItemTemplatePath);
        register(m_defaultFolderTemplatePath);
        register(m_languages);
        register(m_publishToFileClass);
        register(m_disableItemPfs);
        register(m_defaultItemResolverClass);
        register(m_defaultTemplateResolverClass);
        register(m_categoryAuthoringAddForm);
        register(m_useSectionCategories);
        register(m_itemAdapters);
        register(m_defaultSection);
        register(m_useStreamlinedCreation);
        register(m_dhtmlEditorConfig);
        register(m_dhtmlEditorPlugins);
        register(m_hideTemplatesTab);
        register(m_hideAdminTabs);
        register(m_hideTimezone);
        register(m_hideLaunchDate);
        register(m_hideUDCTUI);
        register(m_hideFolderIndexCheckbox);
        register(m_defaultNotificationTime);

        loadInfo();
    }

    public final String getTemplateRoot() {
        return (String) get(m_templateRootPath);
    }

    public final String getDefaultItemTemplatePath() {
        return (String) get(m_defaultItemTemplatePath);
    }

    public final String getDefaultFolderTemplatePath() {
        return (String) get(m_defaultFolderTemplatePath);
    }

    public final String getLanguages() {
        return (String) get(m_languages);
    }

    public final Class getPublishToFileClass() {
        return (Class) get(m_publishToFileClass);
    }

    public final boolean getDisableItemPfs() {
        return ((Boolean) get(m_disableItemPfs)).booleanValue();
    }

    public final Class getDefaultItemResolverClass() {
        return (Class) get(m_defaultItemResolverClass);
    }

    public final Class getDefaultTemplateResolverClass() {
        return (Class) get(m_defaultTemplateResolverClass);
    }

    public final Class getCategoryAuthoringAddForm() {
        return (Class) get(m_categoryAuthoringAddForm);
    }

    public final boolean getUseSectionCategories() {
        return ((Boolean) get(m_useSectionCategories)).booleanValue();
    }

    public final InputStream getItemAdapters() {
        try {
            return ((URL)get(m_itemAdapters)).openStream();
        } catch (IOException ex) {
            throw new UncheckedWrapperException("Cannot read stream", ex);
        }
    }

    public final String getDefaultContentSection() {
        return (String) get(m_defaultSection);
    }

    public final boolean getUseStreamlinedCreation() {
        return ((Boolean) get(m_useStreamlinedCreation)).booleanValue();
    }

    public final DHTMLEditor.Config getDHTMLEditorConfig() {
        return (DHTMLEditor.Config)get(m_dhtmlEditorConfig);
    }
    
    public final String[] getDHTMLEditorPlugins() {
        return (String[])get(m_dhtmlEditorPlugins);
    }

    public final boolean getHideTemplatesTab() {
        return ((Boolean) get(m_hideTemplatesTab)).booleanValue();
    }

    public final boolean getHideAdminTabs() {
        return ((Boolean) get(m_hideAdminTabs)).booleanValue();
    }

    public final boolean getHideTimezone() {
        return ((Boolean) get(m_hideTimezone)).booleanValue();
    }

    public final boolean getHideLaunchDate() {
        return ((Boolean) get(m_hideLaunchDate)).booleanValue();
    }

    public final boolean getHideUDCTUI() {
        return ((Boolean) get(m_hideUDCTUI)).booleanValue();
    }

    public final boolean getHideFolderIndexCheckbox() {
        return ((Boolean) get(m_hideFolderIndexCheckbox)).booleanValue();
    }

    public final int getDefaultNotificationTime() {
        return ((Integer) get(m_defaultNotificationTime)).intValue();
    }

    private class SpecificClassParameter extends ClassParameter {

        private Class m_requiredClass;

        public SpecificClassParameter(final String name,
                                      final int multiplicity,
                                      final Object defaultObj,
                                      final Class requiredClass) {
            super(name, multiplicity, defaultObj);
            m_requiredClass = requiredClass;
        }

        // value != null
        protected Object unmarshal(String value, ErrorList errors) {
            Class theClass = (Class) super.unmarshal(value,errors);
            if (theClass != null) {
                if (!m_requiredClass.isAssignableFrom(theClass)) {
                    errors.add(new ParameterError(this, "class " + value + 
                                                  "  must implement : " + 
                                                  m_requiredClass.getName()));
                }
            }

            return theClass;
        }
    }

    private class DHTMLEditorConfigParameter extends StringParameter {
        public DHTMLEditorConfigParameter(final String name,
                                          final int multiplicity,
                                          final Object defaultObj) {
            super(name, multiplicity, defaultObj);
        }
        
        protected Object unmarshal(String value, ErrorList errors) {
            return DHTMLEditor.Config.valueOf(value);
        }
    }
}
