/**
 * 
 */
package org.richfaces.taglib;

import java.io.IOException;

import javax.el.ELException;
import javax.faces.FacesException;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;

import org.ajax4jsf.webapp.taglib.AjaxComponentHandler;
import org.richfaces.component.UIBeanValidator;
import org.richfaces.validator.FacesBeanValidator;

import com.sun.facelets.FaceletContext;
import com.sun.facelets.FaceletException;
import com.sun.facelets.tag.TagAttribute;
import com.sun.facelets.tag.TagException;
import com.sun.facelets.tag.TagHandler;
import com.sun.facelets.tag.jsf.ComponentConfig;

/**
 * @author asmirnov
 * 
 */
public class AjaxValidatorHandler extends TagHandler {

	/**
	 * A UIComponent for capturing a child UIComponent, representative of the
	 * desired Facet
	 * 
	 * @author Jacob Hookom
	 * 
	 */
	private final static class UIFacet extends UIComponentBase {
		public String getFamily() {
			return null;
		}
	}

	private TagAttribute _event;
	private AjaxComponentHandler _validatorHandler;

	/**
	 * @param config
	 */
	public AjaxValidatorHandler(ComponentConfig config) {
		super(config);
		_event = getAttribute("event");
		_validatorHandler = new AjaxComponentHandler(config);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.sun.facelets.FaceletHandler#apply(com.sun.facelets.FaceletContext,
	 * javax.faces.component.UIComponent)
	 */
	public void apply(FaceletContext ctx, UIComponent parent)
			throws IOException, FacesException, FaceletException, ELException {
		if (parent == null || !(parent instanceof EditableValueHolder)) {
			throw new TagException(this.tag,
					"Parent not an instance of EditableValueHolder: " + parent);
		}
		if (null == parent.getParent()) {
			// New created component, add validator.
			FacesContext facesContext = FacesContext.getCurrentInstance();
			FacesBeanValidator validator = (FacesBeanValidator) facesContext
					.getApplication().createValidator(
							FacesBeanValidator.BEAN_VALIDATOR_TYPE);
			((EditableValueHolder) parent).addValidator(validator);
		}
		if (null != this._event) {
			UIComponent c;
			UIFacet facet = new UIFacet();
			// Find facet for client validation component
			String eventName = _event.getValue();
			String facetName = UIBeanValidator.BEAN_VALIDATOR_FACET + eventName;
			c = parent.getFacet(facetName);
			if (null != c) {
				parent.getFacets().remove(facetName);
				facet.getChildren().add(c);
			}
			this._validatorHandler.apply(ctx, facet);
			c = (UIComponent) facet.getChildren().get(0);
			parent.getFacets().put(facetName, c);

		}
	}

}
