 	import mx.utils.ObjectUtil;
 	
 	import weave.api.WeaveAPI;
+	import weave.api.core.ICallbackCollection;
 	import weave.api.core.IDisposableObject;
 	import weave.api.core.ILinkableObject;
 	import weave.api.getCallbackCollection;

		private var _history:Array = [];
		private var _future:Array = [];
		private var _serial:int = 0;
		private var _lastDiffID:Number = 0;
		private var _undoActive:Boolean = false;
		
		private function handleDiff(diffID:Number = Infinity):void
		{
			if (diffID < _lastDiffID) // more than one diff per frame
			{
				return;
			}
			if (diffID == Infinity) // called as a grouped callback
			{
				StageUtils.callLater(this, handleDiff, [++_lastDiffID]);
				return;
			}
			if (diffID == _lastDiffID) // called 1 frame after grouped callback
			{
				StageUtils.callLater(this, handleDiff, [++_lastDiffID + 1]);
				return;
			}
			
			// diff > lastDiff means it is now 2 frames after the last diff
			
			var state:Object = getSessionState(_subject);
			
			var diff:* = WeaveAPI.SessionManager.computeDiff(_prevState, state);
			if (diff != undefined)
			{
				var backDiff:* = WeaveAPI.SessionManager.computeDiff(state, _prevState);
				if (_undoActive)
					_future.unshift(new LogEntry(_serial++, backDiff, diff)); // reverse
				else
					_history.push(new LogEntry(_serial++, diff, backDiff));
				
				debugHistory(true);
				
				getCallbackCollection(this).triggerCallbacks();
			}
			
			_prevState = state;
			_undoActive = false;
		}

		private function debugHistory(showLastDiff:Boolean):void

		public function SessionStateLog(subject:ILinkableObject)
		{
			_subject = subject;
			_prevState = getSessionState(_subject); // remember the initial state
			registerDisposableChild(_subject, this); // make sure this is disposed when _subject is disposed
			
			var cc:ICallbackCollection = getCallbackCollection(_subject);
			cc.addImmediateCallback(this, immediateCallback);
			cc.addGroupedCallback(this, groupedCallback);
		}
		
		public function dispose():void
