package org.ajax4jsf.context;

import java.io.IOException;
import java.util.Map;
import java.util.Set;

import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.el.VariableResolver;


public abstract class AjaxContext {

	/**
	 * Key for keep request state information in request-scope attributes.
	 */
	public static final String AJAX_CONTEXT_KEY = "ajaxContext";

	public abstract Map getCommonAjaxParameters();

	public abstract String getAjaxActionURL(FacesContext context);

	public abstract String getAjaxActionURL();

	public abstract void setResponseData(Object responseData);

	public abstract Object getResponseData();

	public abstract void setOncomplete(Object oncompleteFunction);

	public abstract Object getOncomplete();

	public abstract void setViewIdHolder(ViewIdHolder viewIdHolder);

	public abstract ViewIdHolder getViewIdHolder();

	public abstract boolean removeRenderedArea(String id);

	public abstract void addRenderedArea(String id);

	public abstract Set getAjaxRenderedAreas();

	public abstract void addComponentToAjaxRender(UIComponent base, String id);

	public abstract void addComponentToAjaxRender(UIComponent component);

	public abstract void addRegionsFromComponent(UIComponent component);

	public abstract Set getAjaxAreasToRender();

	public abstract boolean isAjaxRequest(FacesContext context);

	public abstract boolean isAjaxRequest();

	public abstract void processHeadResources(FacesContext context)
			throws FacesException;

	public abstract void encodeAjaxEnd(FacesContext context, UIComponent component)
			throws IOException;

	public abstract void encodeAjaxBegin(FacesContext context, UIComponent component)
			throws IOException;

	public abstract void renderAjaxRegion(FacesContext context, UIComponent component,
			boolean useFilterWriter) throws FacesException;

	public abstract void renderSubmittedAjaxRegion(FacesContext context, final boolean useFilterWriter);

	public abstract void renderSubmittedAjaxRegion(FacesContext context);

	public static final String SCRIPTS_PARAMETER = "org.ajax4jsf.framework.HEADER_SCRIPTS";
	public static final String STYLES_PARAMETER = "org.ajax4jsf.framework.HEADER_STYLES";
	public static final String RESPONSE_DATA_KEY = "_ajax:data";

	/**
	 * Get instance of current AJAX Context. Instance get by
	 * {@link VariableResolver#resolveVariable(FacesContext, String)} for
	 * variable {@link AjaxContext#AJAX_CONTEXT_KEY}
	 * 
	 * @return memento instance for current request
	 */
	public static AjaxContext getCurrentInstance() {
	FacesContext context = FacesContext.getCurrentInstance();
	return getCurrentInstance(context);
	}

	/**
	 * Get instance of current AJAX Context. Instance get by
	 * {@link VariableResolver#resolveVariable(FacesContext, String)} for
	 * variable {@link AjaxContext#AJAX_CONTEXT_KEY}
	 * 
	 * @param context
	 *                current FacesContext
	 * @return instance of AjaxContext.
	 */
	public static AjaxContext getCurrentInstance(FacesContext context) {
	if (null == context) {
	    throw new NullPointerException("FacesContext is null");
	}
	AjaxContext ajaxContext = (AjaxContext) context.getApplication()
		.getVariableResolver().resolveVariable(context,
			AJAX_CONTEXT_KEY);
	if (null == ajaxContext) {
	    // TODO Create default implementation.
//	    ajaxContext = new AjaxContext();
//	    context.getExternalContext().getRequestMap().put(AJAX_CONTEXT_KEY,
//		    ajaxContext);
	}
	return ajaxContext;
	}

	public AjaxContext() {
		super();
	}
	
	public abstract void release();

	public abstract Map getResponseDataMap();

	public abstract void setAjaxRequest(boolean b);

	public abstract boolean isSelfRender();

	public abstract void setSelfRender(boolean b);

	public abstract String getSubmittedRegionClientId(FacesContext context);

	public abstract void saveViewState(FacesContext context) throws IOException;
}