/*	ServletBridge.java

	Purpose:
		
	Description:
		
	History:
		2013/6/25 by Dennis

	Copyright (C) 2010 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.zssex.ui;

import java.io.Serializable;
import java.io.Writer;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.zkoss.io.NullWriter;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.Execution;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.GenericRichlet;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.sys.DesktopCtrl;
import org.zkoss.zkplus.embed.Renders;

/**
 * A abstract util wrapping {@link Renders} provide easier functionality for a servlet to do job in zk execution
 * @author dennis
 * @since 3.0.0
 */
public abstract class ExecutionBridge implements Serializable {
	private static final long serialVersionUID = -2385003478619811350L;
	
	final protected ServletContext _servletContext;
	final protected HttpServletRequest _request;
	final protected HttpServletResponse _response;
	
	private Desktop _desktop;
	
	public ExecutionBridge(ServletContext servletContext, HttpServletRequest req, HttpServletResponse resp){
		this._servletContext = servletContext;
		this._request = req;
		this._response = resp;
	}
	public void process (){
		if(_desktop!=null){
			throw new IllegalStateException("can't process twice");
		}
		Writer dummy = new NullWriter();
		try {
			Renders.render(_servletContext, _request, _response, 
					new GenericRichlet() {
						public void service(Page page) throws Exception {
							_desktop = page.getDesktop();
							process(Executions.getCurrent());
							((DesktopCtrl)_desktop).removePage(page);
							//the desktop will be destroyed by desktop timeout if it is use in a pure jsp page
							
							//TODO set desktop timeout to very short if this desktop doesn't contains component after load
							//HOW do I know to remove this desktop, it is possible be use after or before here
						}
					}, null, dummy);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(),e);
		}
	}

	
	protected abstract void process(Execution execution) throws Exception;
}
