/*******************************************************************************
 * Copyright © 2005 VHA. All rights reserved
 ******************************************************************************/

package gov.va.med.fw.ui.taglib;

import java.util.HashSet;
import java.util.Set;

import javax.servlet.jsp.JspException;

import org.apache.struts.Globals;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.taglib.TagUtils;
import org.apache.strutsel.taglib.html.ELMessagesTag;
import org.apache.strutsel.taglib.utils.EvalHelper;

/**
 * @author Muddaiah Ranga
 * @version 3.0
 */
public class CustomMessagesTag extends ELMessagesTag {
	/**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = 4411792870795960221L;

	private Set displayedMessages = new HashSet();

	private boolean isDuplicateMessage = false;

	/**
	 * Construct an iterator for the specified collection, and begin looping
	 * through the body once per element.
	 * 
	 * @exception JspException
	 *               if a JSP exception has occurred
	 */
	public int doStartTag() throws JspException {
		evaluateExpressions();

		// Initialize for a new request.
		processed = false;

		// Were any messages specified?
		ActionMessages messages = null;

		// Make a local copy of the name attribute that we can modify.
		String name = this.name;

		if (message != null && "true".equalsIgnoreCase(message)) {
			name = Globals.MESSAGE_KEY;
		}

		try {
			messages = TagUtils.getInstance().getActionMessages(pageContext, name);
		}
		catch (JspException e) {
			TagUtils.getInstance().saveException(pageContext, e);
			throw e;
		}

		// Acquire the collection we are going to iterate over
		this.iterator = (property == null) ? messages.get() : messages
				.get(property);

		// Store the first value and evaluate, or skip the body if none
		if (!this.iterator.hasNext()) {
			return SKIP_BODY;
		}

		ActionMessage report = (ActionMessage) this.iterator.next();
		String msg = TagUtils.getInstance().message(pageContext, bundle, locale,
				report.getKey(), report.getValues());

		if (msg == null) {
			pageContext.removeAttribute(id);
		}
		else {
			pageContext.setAttribute(id, msg);
			displayedMessages.add(msg);
		}

		if (header != null && header.length() > 0) {
			String headerMessage = TagUtils.getInstance().message(pageContext,
					bundle, locale, header);
			if (headerMessage != null) {
				TagUtils.getInstance().write(pageContext, headerMessage);
			}
		}

		// Set the processed variable to true so the
		// doEndTag() knows processing took place
		processed = true;

		return (EVAL_BODY_BUFFERED);
	}

	/**
	 * Make the next collection element available and loop, or finish the
	 * iterations if there are no more elements.
	 * 
	 * @exception JspException
	 *               if a JSP exception has occurred
	 */
	public int doAfterBody() throws JspException {
		// Render the output from this iteration to the output stream
		if (bodyContent != null) {
			if (!isDuplicateMessage) {
				TagUtils.getInstance().writePrevious(pageContext,
						bodyContent.getString());
			}
			bodyContent.clearBody();
		}
		isDuplicateMessage = false;

		// Decide whether to iterate or quit
		if (iterator.hasNext()) {
			ActionMessage report = (ActionMessage) iterator.next();
			String msg = TagUtils.getInstance().message(pageContext, bundle,
					locale, report.getKey(), report.getValues());
			if (displayedMessages.contains(msg)) {
				msg = null;
				isDuplicateMessage = true;
			}

			if (msg == null) {
				pageContext.removeAttribute(id);
			}
			else {
				pageContext.setAttribute(id, msg);
				displayedMessages.add(msg);
			}

			return (EVAL_BODY_AGAIN);
		}
		else {
			return (SKIP_BODY);
		}

	}

	/**
	 * Processes all attribute values which use the JSTL expression evaluation
	 * engine to determine their values.
	 * 
	 * @exception JspException
	 *               if a JSP exception has occurred
	 */
	private void evaluateExpressions() throws JspException {
		String string = null;

		if ((string = EvalHelper.evalString("id", getIdExpr(), this, pageContext)) != null)
			setId(string);

		if ((string = EvalHelper.evalString("bundle", getBundleExpr(), this,
				pageContext)) != null)
			setBundle(string);

		if ((string = EvalHelper.evalString("locale", getLocaleExpr(), this,
				pageContext)) != null)
			setLocale(string);

		if ((string = EvalHelper.evalString("name", getNameExpr(), this,
				pageContext)) != null)
			setName(string);

		if ((string = EvalHelper.evalString("property", getPropertyExpr(), this,
				pageContext)) != null)
			setProperty(string);

		if ((string = EvalHelper.evalString("header", getHeaderExpr(), this,
				pageContext)) != null)
			setHeader(string);

		if ((string = EvalHelper.evalString("footer", getFooterExpr(), this,
				pageContext)) != null)
			setFooter(string);

		if ((string = EvalHelper.evalString("message", getMessageExpr(), this,
				pageContext)) != null)
			setMessage(string);
	}

	public void release() {
		super.release();
		displayedMessages.clear();
	}
}
