package com.smartgwt.sample.client.tinymce;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.core.client.JavaScriptObject;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.form.fields.CanvasItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.events.FormItemInitHandler;
import com.smartgwt.client.widgets.form.fields.events.ShowValueEvent;
import com.smartgwt.client.widgets.form.fields.events.ShowValueHandler;
import com.smartgwt.client.widgets.grid.ListGrid;

/**
 * Implements TinyMCE editor as a CanvasItem
 */
public class TinyMCECanvasItem extends CanvasItem {

	/**
	 * A map to lookup canvasItem instances by MCE instance id
	 */
	private static Map<String, TinyMCECanvasItem> instanceMap = new HashMap<String, TinyMCECanvasItem>();
	
	
	private static final String WIDTH = "700px";
	private static final String HEIGHT = "200px";
	
	private String currentValue = "";
	private TinyMCECanvas editor;
	
	public TinyMCECanvasItem(String name) {
		super(name);
		setupEditor(WIDTH, HEIGHT);
	}
	public TinyMCECanvasItem(JavaScriptObject jso) {
		super(jso);
		setupEditor(WIDTH, HEIGHT);
	}
	public TinyMCECanvasItem(String name, String title) {
		super(name, title);
		setupEditor(WIDTH, HEIGHT);
	}

	public TinyMCECanvasItem() {
		super();
		setupEditor(WIDTH, HEIGHT);
	}
	/**
	 * Get the current from the CanvasItem for an editor instance.
	 * @param instanceId The editor instance ID.
	 * @return The currently stored value.
	 */
	public static String getCurrentValue(String instanceId) {
		TinyMCECanvasItem item = instanceMap.get(instanceId);
		return item.currentValue;
	}

	private void setCurrentValue(String currentValue) {
		this.currentValue = currentValue;
	}

	/**
	 * Update the current value in both the editor instance and
	 * the private CanvasItem variable. This uses CanvasItem.storeValue
	 * but also calls setEditValue if the CanvasItem is in a grid.
	 * The call to setEditValue should not be necessary, but see
	 * this forum post for the Isomorphic response.
	 * http://forums.smartclient.com/showthread.php?t=29530
	 * 
	 * @param instanceId The editor instance ID.
	 * @param value The new value to store.
	 */
	public static void updateValue(String instanceId, String value) {
		SC.logDebug("storing value "+value+" for instance "+instanceId);
 		TinyMCECanvasItem instanceItem = instanceMap.get(instanceId);
 		SC.logDebug("instanceItem is "+instanceItem.getName()+" in form "+instanceItem.getForm().getID());
 		instanceItem.setCurrentValue(value==null ? "" : value);
 		instanceItem.storeValue(value==null ? "" : value); 	
		try {
	 		// The only way I know to tell if the CanvasItem is in a grid is to try to get the grid.
			ListGrid grid = ListGrid.getOrCreateRef(instanceItem.getAttributeAsJavaScriptObject("grid"));
			SC.logDebug("Updating grid with value for instanceId "+instanceId);
			grid.setEditValue(grid.getEditRow(), instanceItem.getName(), value);
		} catch (Exception e) {
			SC.logDebug("Exception getting grid for instanceId "+instanceId+" : "+e.getMessage());
		}
	}
	
	
	/**
	 * Create a new TinyMCECanvas and place it in this CanvasItem.
	 * Set selected properties and add a ShowValueHandler to put
	 * new contents into the editor. The editor widget is initialized
	 * by a FormItemInitHandler. This seems to be the only time
	 * we can safely look for the DOM element to replace with an editor.
	 *  
	 * @param width The width for this CanvasItem.
	 * @param height The height for this CanvasItem.
	 */
	private void setupEditor(String width, String height) {
		
		// Set some properties
		setShouldSaveValue(true);
		setApplyPromptToCanvas(false);
		setAutoDestroy(true);
		setWidth(width);
		setHeight(height);
		setOverflow(Overflow.VISIBLE);
		final TinyMCECanvasItem me = this;

        // Use a FormItemInitHandler to initialize the editor
        setInitHandler(new FormItemInitHandler() {
			
			@Override
			public void onInit(FormItem item) {
				// Create a new editor canvas
				editor = new TinyMCECanvas(); 

				// Add the editor element ID to our map of instances
				instanceMap.put(editor.getElementID(), me);
				
				// Set the editor as this items canvas
		        setCanvas(editor);
				editor.initCanvas();
			}
		});

        // Use a ShowValueHandler to put text into the editor
		addShowValueHandler(new ShowValueHandler() {
			
			@Override
			public void onShowValue(ShowValueEvent event) {
				SC.logDebug("ShowValueEvent is putting "+event.getDataValue()+" in "+editor.getElementID());
				String dataValue = (String) event.getDataValue();
				setCurrentValue(dataValue);
				TinyMCE.updateContent(editor.getElementID(), dataValue);
			}
		});
		
	}
	
}

