/* JSFSpreadsheet.java

	Purpose:
		
	Description:
		
	History:
		Tue Sept 14 08:48:59 TST 2010, Created by Ashish Dasnurkar

Copyright (C) 2010 Potix Corporation. All Rights Reserved.

 */
package org.zkoss.zss.jsf.ui;

import java.io.IOException;

import javax.el.ELContext;
import javax.el.ValueExpression;
import javax.faces.component.FacesComponent;
import javax.faces.component.StateHelper;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import org.zkoss.lang.Strings;
import org.zkoss.util.logging.Log;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zss.api.model.Book;
import org.zkoss.zss.jsf.ui.impl.ObjectHolderContext;
import org.zkoss.zss.jsf.ui.impl.JSFComponentBase;
import org.zkoss.zss.ui.Spreadsheet;

/**
 * Represents a custom JSF component that wraps ZK Spreadsheet component
 * 
 * @author dennis
 * 
 */
@FacesComponent(value = "org.zkoss.zss.Spreadsheet")
public class JSFSpreadsheet extends JSFComponentBase {
	private static final Log log = Log.lookup(JSFSpreadsheet.class);

	public Spreadsheet getSpreadsheet() {
		return (Spreadsheet) getZKComponent();
	}

	@Override
	protected Component newZKComponent() {
		return new Spreadsheet();
	}

	@Override
	public void encodeBegin(final FacesContext context) throws IOException {
		ResponseWriter writer = context.getResponseWriter();
		String id =  getClientId(context);
		writer.startElement("div", this);//can't hook as a input, Mojarra process input in special way
		writer.writeAttribute("id", id, "id");
//		writer.writeAttribute("class", "zsshook", null);
		StateHelper sh = getStateHelper();
		
		//handle html properties
		String sclass = (String)getStateProperty("sclass");
		String style = (String)getStateProperty("style");
		String width = (String)getStateProperty("width");
		String height = (String)getStateProperty("height");
		
		if(!Strings.isEmpty(sclass)){
			writer.writeAttribute("class", "zssjsf "+sclass,null);
		}else{
			writer.writeAttribute("class", "zssjsf",null);
		}
		if(!Strings.isEmpty(width)){
			style = appendStyle(style,"width",width);
		}
		if(!Strings.isEmpty(height)){
			style = appendStyle(style,"height",height);
		}
		if(!Strings.isEmpty(style)){
			writer.writeAttribute("style", style, null);
		}
		
		super.encodeBegin(context);
		
		//fix for the tomcat invalid chunk wran when submit
		String zssid = getZKComponent().getUuid();
		writer.append("<script type=\"text/javascript\">zk.afterLoad(function(){");
		writer.append("zssjsf.fixSize('"+zssid+"');");
		writer.append("zssjsf.fixTomcatTrunkIssue('"+zssid+"');");
		writer.append("});</script>");
		
		writer.endElement("div");
		
		
	}
	
	@Override
	protected void releaseResource(Component compToBeDrop) {
		((Spreadsheet)compToBeDrop).setBook(null);
	}

	@Override
	public void processUpdates(FacesContext context) {
		if (context == null) {
			throw new NullPointerException();
		}

		// Skip processing if our rendered flag is false
		if (!isRendered()) {
			return;
		}

		super.processUpdates(context);
		try {
			updateBook(context);
		} catch (RuntimeException e) {
			context.renderResponse();
			throw e;
		}
	}

	
	protected void updateBook(FacesContext context) {
		if (context == null) {
			throw new NullPointerException();
		}

		ValueExpression ve = getValueExpression("book");
		if (ve != null) {
			ELContext ctx = context.getELContext();
			if(!ve.isReadOnly(ctx)){
				Spreadsheet ss = getSpreadsheet();
				//what if desktop was removed because of timeout or other cause?
				
				//ZSS-641, try to get data from holder if ss not found
				Book book = ss==null?
						(Book)ObjectHolderContext.getObjectIfAny(getZKDesktopId(), getZKComponentUuid()+".book")
						:ss.getBook();
				ve.setValue(context.getELContext(), book);
			}
		}
		ve = getValueExpression("selectedSheetName");
		if (ve != null) {
			ELContext ctx = context.getELContext();
			if(!ve.isReadOnly(ctx)){
				Spreadsheet ss = getSpreadsheet();
				//what if desktop was removed because of timeout or other cause?
				
				//ZSS-641, try to get data from holder if ss not found
				String nm= ss==null?
						(String)ObjectHolderContext.getObjectIfAny(getZKDesktopId(), getZKComponentUuid()+".selectedSheetName")
						:ss.getSelectedSheetName();
				ve.setValue(context.getELContext(), nm);
			}
		}
	}
	@Override
	protected DeadComponentHolderListener newDeadComponentHolderListener() {
		return new DeadSSHolderListener();
	}
	
	//ZSS-641, holder to hold data for spreadsheet which are possible to be lost after remove desktop
	static protected class DeadSSHolderListener extends DeadComponentHolderListener{
		private static final long serialVersionUID = 1L;

		@Override
		protected void holdData(Desktop desktop, Component comp) {
			if(comp==null)
				return;
			Spreadsheet ss = (Spreadsheet)comp;
			ObjectHolderContext.putObject(desktop.getId(), getComponentUuid()+".book", ss.getBook());
			ObjectHolderContext.putObject(desktop.getId(), getComponentUuid()+".selectedSheetName", ss.getSelectedSheetName());
		}
	}
}
