/**
 * 
 */
package org.ajax4jsf.portlet.application;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.faces.FacesException;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.portlet.ActionRequest;
import javax.portlet.RenderRequest;

/**
 * @author asmirnov
 * 
 */
public class PortletViewState implements Serializable {

    /**
         * 
         */
    private static final long serialVersionUID = 5630637804542426709L;

    public static final String SAVED_VIEW_ATTRIBUTE = PortletViewState.class
	    .getName();

    private Map messages = new HashMap();

    private Object treeStructure;

    private Object componentsState;

    private UIViewRoot viewRoot;
    
    private String viewId;
    
    private Map requestScopeBeans;


    /**
	 * @return the requestScopeBeans
	 */
	public Map getRequestScopeBeans() {
		return requestScopeBeans;
	}


	/**
	 * @param requestScopeBeans the requestScopeBeans to set
	 */
	public void setRequestScopeBeans(Map requestScopeBeans) {
		this.requestScopeBeans = requestScopeBeans;
	}


	/**
	 * @return the viewId
	 */
	public String getViewId() {
		return viewId;
	}


	/**
	 * @param viewId the viewId to set
	 */
	public void setViewId(String viewId) {
		this.viewId = viewId;
	}


	/**
         * @param facesContext
         */
    public void saveMessages(FacesContext facesContext) {
	Iterator idsWithMessages = facesContext.getClientIdsWithMessages();
	while (idsWithMessages.hasNext()) {
	    String id = (String) idsWithMessages.next();
	    Iterator messages = facesContext.getMessages(id);
	    while (messages.hasNext()) {
		FacesMessage message = (FacesMessage) messages.next();
		addMessage(id, message);
	    }
	}
    }


    /**
         * @param facesContext
         */
    public void restoreMessages(FacesContext facesContext) {
	Iterator idsWithMessages = getClientIdsWithMessages();
	while (idsWithMessages.hasNext()) {
	    String id = (String) idsWithMessages.next();
	    Iterator messages = getMessages(id);
	    while (messages.hasNext()) {
		FacesMessage message = (FacesMessage) messages.next();
		facesContext.addMessage(id, message);
	    }
	}
    }

    /**
         * @return the _messages
         */
    public Map getMessages() {
	return messages;
    }

    /**
         * @param _messages
         *                the _messages to set
         */
    public void setMessages(Map _messages) {
	this.messages = _messages;
    }

    /**
         * @return the _viewRoot
         */
    public UIViewRoot getViewRoot() {
	return viewRoot;
    }

    /**
         * @param root
         *                the _viewRoot to set
         */
    public void setViewRoot(UIViewRoot root) {
	viewRoot = root;
    }

    public void addMessage(String clientId, FacesMessage message) {
	List list = (List) messages.get(clientId);
	if (list == null) {
	    list = new ArrayList();
	    messages.put(clientId, list);
	}
	list.add(message);
    }

    public Iterator getClientIdsWithMessages() {
	return (messages.keySet().iterator());
    }

    public Iterator getMessages(String clientId) {
	List list = (List) messages.get(clientId);
	if (list != null) {
	    return (list.iterator());
	} else {
	    return (Collections.EMPTY_LIST.iterator());
	}
    }

    /**
         * @return the componentsState
         */
    public Object getComponentsState() {
	return componentsState;
    }

    /**
         * @param componentsState
         *                the componentsState to set
         */
    public void setComponentsState(Object componentsState) {
	this.componentsState = componentsState;
    }

    /**
         * @return the treeStructure
         */
    public Object getTreeStructure() {
	return treeStructure;
    }

    /**
         * @param treeStructure
         *                the treeStructure to set
         */
    public void setTreeStructure(Object treeStructure) {
	this.treeStructure = treeStructure;
    }

}
