package org.appfuse.webapp.taglib;

import org.apache.commons.validator.Field;
import org.apache.commons.validator.Form;
import org.apache.commons.validator.ValidatorResources;

import org.apache.struts.Globals;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionErrors;

import org.apache.struts.taglib.html.Constants;
import org.apache.struts.taglib.html.FormTag;

import org.apache.struts.util.RequestUtils;
import org.apache.struts.util.ResponseUtils;

import org.apache.struts.validator.ValidatorPlugIn;

import java.util.Iterator;
import java.util.Locale;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport;


/**
 * <p>This class is designed to render a <label> tag for labeling your forms and
 * adds an asterik (*) for required fields.  It was originally written by Erik
 * Hatcher (http://www.ehatchersolutions.com/JavaDevWithAnt/).</p>
 *
 * <p>It is designed to be used as follows:
 * <pre>&lt;appfuse:label key="userForm.username" /&gt;</pre>
 * </p>
 *
 * @jsp.tag name="label" bodycontent="empty"
 */
public class LabelTag extends TagSupport {
    //~ Instance fields ========================================================

    protected String key = null;
    protected String styleClass = null;
    protected String errorClass = null;

    //~ Methods ================================================================

    public int doStartTag() throws JspException {
        // Look up this key to see if its a field of the current form
        boolean requiredField = false;
        boolean validationError = false;

        ValidatorResources resources =
            (ValidatorResources) pageContext.getServletContext()
            								.getAttribute(ValidatorPlugIn.VALIDATOR_KEY);

        Locale locale =
            (Locale) pageContext.getAttribute(Globals.LOCALE_KEY,
                                              PageContext.SESSION_SCOPE);

        if (locale == null) {
            locale = Locale.getDefault();
        }

        FormTag formTag =
            (FormTag) pageContext.getAttribute(Constants.FORM_KEY,
                                               PageContext.REQUEST_SCOPE);
        String formName = formTag.getBeanName();

        //String formName = mapping.getAttribute();
        System.out.println("formName: " + formName);

        String fieldName = key.substring(formName.length() + 1);

        if (resources != null) {
            Form form = resources.get(locale, formName);

            if (form != null) {
                Field field = (Field) form.getFieldMap().get(fieldName);

                if (field != null) {
                    if (field.isDependency("required")) {
                        requiredField = true;
                    }
                }
            }
        }

        ActionErrors errors =
            (ActionErrors) pageContext.getAttribute(Globals.ERROR_KEY,
                                                    PageContext.REQUEST_SCOPE);

        if (errors != null) {
            Iterator errorIterator = errors.get(fieldName);

            if (errorIterator.hasNext()) {
                validationError = true;
            }
        }

        // Retrieve the message string we are looking for
        String message =
            RequestUtils.message(pageContext, Action.MESSAGES_KEY,
                                 Globals.LOCALE_KEY, key);

        if (message == null) {
            JspException e =
                new JspException("Cannot find message for key: " + key);
            RequestUtils.saveException(pageContext, e);
            throw e;
        }

        String cssClass = (styleClass != null) ? styleClass : "label";
        String cssErrorClass = (errorClass != null) ? errorClass : "labelError";

        if ((message == null) || "".equals(message.trim())) {
            message = "";
        } else {
            message =
                "<label for=\"" + fieldName + "\" class=\"" +
                (validationError ? cssErrorClass : cssClass) + "\">" + message +
                (requiredField ? "*" : "") + "*</label>";
        }

        // Print the retrieved message to our output writer
        ResponseUtils.write(pageContext, message);

        // Continue processing this page
        return (SKIP_BODY);
    }

    /**
     * @jsp.attribute required="true"
     */
    public void setKey(String key) {
        this.key = key;
    }

    /**
     * Setter for assigning a CSS class, default is label.
     *
     * @jsp.attribute required="false"
     */
    public void setStyleClass(String styleClass) {
        this.styleClass = styleClass;
    }

    /**
     * Setter for assigning a CSS class when errors occur,
     * defaults to labelError.
     *
     * @jsp.attribute required="false"
     */
    public void setErrorClass(String errorClass) {
        this.errorClass = errorClass;
    }
}

