 import mx.binding.utils.BindingUtils;
 import mx.containers.VBox;
 import mx.core.IUIComponent;
+import mx.core.UIComponent;
 import mx.utils.ObjectUtil;
 
 import weave.api.core.ILinkableHashMap;

	import weave.api.ui.ISelectableAttributes;
	import weave.core.LinkableBoolean;
	import weave.core.LinkableNumber;
	import weave.core.SessionManager;
	import weave.core.UIUtils;
	import weave.primitives.WeaveTreeItem;


internal class JsonSynchronizer
{
	public static function get available():Boolean
	{
		return ClassUtils.getClassDefinition('JSON') != null;
	}
	
	public function JsonSynchronizer(linkableVariable:ILinkableVariable, host:UIComponent, prop:String, delay:uint = 500)
	{
		this.lv = linkableVariable;
		this.host = host;
		this.prop = prop;
		
		getCallbackCollection(lv).addImmediateCallback(host, handleObject, true);
		BindingUtils.bindSetter(EventUtils.generateDelayedCallback(linkableVariable, handleJson, delay, true), this.host, this.prop);
	}
	
	public var JSON:Object = ClassUtils.getClassDefinition('JSON');
	public var lv:ILinkableVariable;
	public var host:UIComponent;
	public var prop:String;
	private var refreshPending:Boolean;
	
	private function handleObject():void
	{
		refreshPending = true;
		refreshHostOnFocusOut();
	}
	
	private function refreshHostOnFocusOut():void
	{
		if (!refreshPending)
			return;
		
		if (UIUtils.hasFocus(host))
		{
			host.callLater(refreshHostOnFocusOut);
		}
		else
		{
			refreshPending = false;
			host[prop] = JSON.stringify(lv.getSessionState());
			if (host.errorString)
				host.errorString = null;
		}
	}
	
	private function handleJson(value:* = null):void
	{
		// do nothing if the host component does not have focus
		if (!UIUtils.hasFocus(host))
			return;
		
		if (!refreshPending)
		{
			refreshPending = true;
			refreshHostOnFocusOut();
		}
		
		var string:String = value;
		var object:Object;
		try
		{
			object = JSON.parse(value);
			if (host.errorString)
				host.errorString = null;
		}
		catch (e:Error)
		{
			// do nothing because user input was invalid
			host.errorString = "Invalid JSON";
			return;
		}
		
		lv.setSessionState(object);
	}
}
