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

import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.ParameterEvent;
import com.arsdigita.bebop.event.ParameterListener;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.RadioGroup;
import com.arsdigita.bebop.form.TextArea;
import com.arsdigita.bebop.form.TextField;
import com.arsdigita.bebop.form.Widget;
import com.arsdigita.bebop.parameters.NotNullValidationListener;
import com.arsdigita.bebop.parameters.TrimmedStringParameter;
import com.arsdigita.categorization.Category;
import com.arsdigita.categorization.CategoryCollection;
import com.arsdigita.cms.ui.BaseForm;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.xml.Element;

import org.apache.log4j.Logger;


/**
 * A form which creates a new category. Extends the edit form for
 * convenience.
 *
 * @author Michael Pih
 * @author Stanislav Freidin &lt;sfreidin@redhat.com&gt;
 * @author Justin Ross &lt;jross@redhat.com&gt;
 * @version $Id: //cms/dev/src/com/arsdigita/cms/ui/category/BaseCategoryForm.java#14 $
 */
class BaseCategoryForm extends BaseForm {
    private static final Logger s_log = Logger.getLogger
        (BaseCategoryForm.class);

    final CategoryRequestLocal m_parent;
    final TextField m_name;
    final TextArea m_description;
    final TextField m_url;
    final RadioGroup m_isAbstract;
    final RadioGroup m_isEnabled;
    final Label m_script = new Label(
        "<script language=\"javascript\">\n" +
        "    var defaulting = false;\n" +
        "\n" +
        "    function urlize(name) {\n" +
        "        var result = \"\";\n" +
        "        for (var i = 0; i < name.length; i++) {\n" +
        "            result = result + substitute(name.charAt(i));\n" +
        "        }\n" +
        "        return escape(result);\n" +
        "    }\n" +
        "\n" +
        "    function substitute(c) {\n" +
        "        switch (c) {\n" +
        "            case \" \":\n" +
        "                return \"-\";\n" +
        "            case \"'\":\n" +
        "            case \",\":\n" +
        "            case \":\":\n" +
        "            case \";\":\n" +
        "            case \"?\":\n" +
        "            case \"!\":\n" +
        "                return \"\";\n" +
        "            default:\n" +
        "                return c.toLowerCase();\n" +
        "        }\n" +
        "    }\n" +
        "</script>",
        false
        );


    private final static String NAME        = "name";
    private final static String DESCRIPTION = "description";
    private final static String URL         = "url";
    private final static String IS_ABSTRACT = "isAbstract";
    private final static String IS_ENABLED = "isEnabled";

    /**
     * Constructor.
     */
    BaseCategoryForm(final String key,
                     final GlobalizedMessage heading,
                     final CategoryRequestLocal parent) {
        super(key, heading);

        m_parent = parent;

        m_name = new TextField(new TrimmedStringParameter(NAME));
        addField(gz("cms.ui.name"), m_name);

        m_name.setSize(30);
        m_name.setMaxLength(200);
        m_name.addValidationListener(new NotNullValidationListener());
        m_name.setOnFocus("if (this.form." + URL + ".value == '') { " +
                          " defaulting = true; this.form." + URL +
                          ".value = urlize(this.value); }");
        m_name.setOnKeyUp("if (defaulting) { this.form." + URL +
                          ".value = urlize(this.value) }");

        // is abstract?
        m_isAbstract = new RadioGroup(IS_ABSTRACT);
        m_isAbstract.addOption(new Option("no", new Label(gz("cms.ui.no"))));
        m_isAbstract.addOption(new Option("yes", new Label(gz("cms.ui.yes"))));
        addField(gz("cms.ui.category.is_not_abstract"),m_isAbstract);

        // is enabled?
        m_isEnabled = new RadioGroup(IS_ENABLED);
        m_isEnabled.addOption(new Option("no", new Label(gz("cms.ui.no"))));
        m_isEnabled.addOption(new Option("yes", new Label(gz("cms.ui.yes"))));
        addField(gz("cms.ui.category.is_enabled"),m_isEnabled);


        m_description = new TextArea
            (new TrimmedStringParameter(DESCRIPTION));
        addField(gz("cms.ui.description"), m_description);

        m_description.setWrap(TextArea.SOFT);
        m_description.setRows(5);
        m_description.setCols(40);

        // URL
        // JavaScript auto-url generation is off by default.
        // It is turned on under the following circumstances
        //
        // * If the url is null, upon starting edit of the title
        // * If the url is null, upon finishing edit of name
        //
        // The rationale is that, auto-url generation is useful
        // if the url is currently null, but once a name has been
        // created you don't want to subsequently change it since
        // it breaks URLs & potentially overwrites the user's
        // customizations.
        m_url = new TextField(new TrimmedStringParameter(URL));
        m_url.setSize(30);
        m_url.setMaxLength(200);
        m_url.addValidationListener(new NotNullValidationListener());
        m_url.setOnFocus("defaulting = false");
        m_url.setOnBlur("if (this.value == '') " +
                        "{ defaulting = true; this.value = urlize(this.form." + NAME +
                        ".value) }");
        addField(gz("cms.ui.category.url"),m_url);

        addAction(new Finish());
        addAction(new Cancel());
    }

    public void generateXML(PageState ps, Element parent) {
        m_script.generateXML(ps, parent);
        super.generateXML(ps, parent);
    }

    class NameUniqueListener implements ParameterListener {
        private final CategoryRequestLocal m_category;
        private final Widget m_widget;
        private final int m_type;
        public final static int NAME_FIELD = 1;
        public final static int URL_FIELD = 2;

        NameUniqueListener(final CategoryRequestLocal category) {
            this(category,m_name,NAME_FIELD);
        }
        NameUniqueListener(final CategoryRequestLocal category,
                           Widget widget, int type) {
            m_category = category;
            m_widget = widget;
            m_type = type;
        }

        public final void validate(final ParameterEvent e)
                throws FormProcessException {
            final PageState state = e.getPageState();
            final String title = (String) m_widget.getValue(state);

            final Category parent = m_parent.getCategory(state);

            final CategoryCollection children = parent.getChildren();

            while (children.next()) {
                final Category child = children.getCategory();
                String compField =
                    (m_type == URL_FIELD) ? child.getURL() : child.getName();
                if (compField.equalsIgnoreCase(title)
                        && (m_category == null
                            || !m_category.getCategory(state).equals(child))) {
                    throw new FormProcessException
                        (lz("cms.ui.category.name_not_unique"));
                }
            }
        }
    }
}
