


//todo throw if already defined
/*
document.onmouseup = mouseUp;
document.onmousemove = mouseMove;

var draggedWidget  = null;
var mouseOffset = null;
var draggableWidgets = new Array();
var currentZIndex = 100;
var widgets = new Array();
*/


/*

*/


/*
 * Is able to manage lots of different kinds of widgets.
 * It keeps order, facilitates focus, dragging, ignoring scrolling etc.
 *
 */
function WidgetManager()
{
	this.draggedWidget = null;
	this.mouseOffset = null;
	//todo floatingWidgets
	this.draggableWidgets = new Array();
	this.currentZIndex = 100;
	this.widgets = new Array();
}




/**
 *
 *
 */
WidgetManager.prototype.registerDraggableWidget = function(widget)
{
	//administer order
	this.draggableWidgets[widget.getDragSelectElement().id] = widget;

	widget.getDOMElement().style.zIndex = this.currentZIndex++;

	widget.getDragSelectElement().onmousedown = function(event)
	{
		var draggableWidget = widgetengine.draggableWidgets[this.id];
		document.body.style.cursor = 'move';
		widgetengine.draggedWidget = draggableWidget;
		//todo rename: is offset from element position
		widgetengine.mouseOffset = getMouseOffsetFromElementPosition(this, event);
	}

	widget.getDOMElement().onmousedown = function(event)
	{
		this.style.zIndex = widgetengine.currentZIndex++;
		var currentWidget = widgetengine.widgets[this.id];
		widgetengine.activateCurrentWidget(currentWidget);
//		widgetengine.draggedWidget = currentWidget;
	}

	this.activateCurrentWidget(widget);
}

/**
 * Deactivates former focussed (draggable) widget and activates current.
 *
 */
WidgetManager.prototype.activateCurrentWidget = function(currentWidget)
{
	for(var draggableId in this.draggableWidgets)
	{
		var widget = this.draggableWidgets[draggableId];
		if(widget != null && widget != currentWidget)
		{
			widget.onBlur();
		}
	}
	currentWidget.onFocus();
}







/////////////////////////
//                     //
//  Widget Management  //
//                     //
/////////////////////////



WidgetManager.prototype.deployWidget = function(newWidget, x, y)
{
	var widget = this.widgets[newWidget.getId()];
	if(widget == null)
	{
		this.widgets[newWidget.getId()] = newWidget;

    	//LAYOUT: determine position / size

		var canvas = document.body;//getElementById('canvas');
		if(typeof x == 'undefined' || x == null)
		{
			var x = 25;
		}
		if(typeof y == 'undefined' || y == null)
		{
			var y = 25;
		}
		if(canvas != null)
    	{
			var element = document.getElementById(newWidget.getId());
    		if(element == null)
            {
    			element = document.createElement('div');

				//is this necessary?
				//use prefix 'widget_'
				element.setAttribute('id', newWidget.getId());

				canvas.appendChild(element);
			}
    		newWidget.setDOMElement(element);
		}
		if(newWidget.ignoresPageScroll)
		{
			var scrollPos = getScrollOffset();
			x = x + scrollPos.x;
			y = y + scrollPos.y;
		}
		newWidget.draw(x, y);
    	newWidget.onDeploy();
	}
	else
	{
    	return widget;
	}
	return newWidget;
}

WidgetManager.prototype.destroyWidget = function(widgetId)
{
	var widget = this.widgets[widgetId];
	if(widget != null)
	{
		//call widget destructor
		widget.onDestroy();

    	var canvas = document.body;//getElementById('canvas');
    	if(canvas != null)
    	{
			var element = document.getElementById(widgetId);
    		if(element != null)
            {
				canvas.removeChild(element);
			}
		}
		var draggableElement = widget.getDragSelectElement();
		if(draggableElement != null)
		{
			this.draggableWidgets[draggableElement.id] = null;
		}
		this.widgets[widgetId] = null;
	}
}



WidgetManager.prototype.getWidget = function(id)
{
	return this.widgets[id];
}

WidgetManager.prototype.containsWidget = function(id)
{
	return this.widgets[id] != null;
}






///////////////////////
//                   //
//  Abstract Widget  //
//   (base class)    //
//                   //
///////////////////////

function Widget()
{
	this.id = 'Widget';
	this.height = 0;
	this.width = 0;
	this.top = 0;
	this.left = 0;
	//element that must be clicked to drag the widget
	this.dragActivationElement = null;
	this.ignoresPageScroll = false;
}


Widget.prototype.getId = function()
{
	return this.id;
};

//(multiple) inherit members here...

Widget.prototype.setPosition = function(x, y)
{
	this.top = y;
	this.left = x;
	this.refreshElementPosition();
}


Widget.prototype.move = function(x, y)
{
	this.top += y;
	this.left += x;
	this.refreshElementPosition();
}

Widget.prototype.refreshElementPosition = function()
{
	if(typeof this.element != 'undefined')
	{
		this.element.style.top = this.top + 'px';
		this.element.style.left = this.left + 'px';
	}
}

Widget.prototype.getDragSelectElement = function()
{
	return this.dragActivationElement;
};


Widget.prototype.setDOMElement = function(element)
{
	this.element = element; // how about coords (x, y) ?
	if(this.dragActivationElement == null)
	{
		this.dragActivationElement = element;
	}
};


Widget.prototype.getDOMElement = function()
{
	return this.element;
};


Widget.prototype.getHeight = function()
{
	return this.height;
};


Widget.prototype.getWidth = function()
{
	return this.width;
};

Widget.prototype.draw = function(left, top)// + mode
{
	//todo provide a nice sample implentation
	alert('\'draw\' not implemented');
};

Widget.prototype.onDestroy = function()
{
};


Widget.prototype.onDeploy = function()
{
};


Widget.prototype.refresh = function()
{
}

Widget.prototype.onFocus = function()
{
};


Widget.prototype.onBlur = function()
{
};

Widget.prototype.processJavaScript = function(input)
{

//	alert('processJavaScript:' + input);
	try
	{
		eval('' + input);
	}
	catch(e)
	{
		alert('Error: ' + e.message);
	}
};


Widget.prototype.setHTML = function(data)
{
	if(this.element != null)
	{
		this.element.innerHTML = data;
	}
};


Widget.prototype.saveState = function() //JSON?
{
};







var widgetengine = new WidgetManager();





function dropWidget(event)
{
	widgetengine.draggedWidget = null;
	document.body.style.cursor = 'auto';
}


function dragWidget(event)
{
	event = event || window.event;
	if(widgetengine.draggedWidget != null)
	{
		var mousePos = getMousePositionInWindow(event);
		widgetengine.draggedWidget.setPosition(mousePos.x - widgetengine.mouseOffset.x, mousePos.y - widgetengine.mouseOffset.y);
//		return false;
	}
}

var savedScrollPos = getScrollOffset();

function scroll(event)
{
//	window.status='SCROLLING';
	//todo update relatively positioned widgets
	var scrollPos = getScrollOffset();

	var offsetX = scrollPos.x - savedScrollPos.x;
	var offsetY = scrollPos.y - savedScrollPos.y;

	for(var draggableId in widgetengine.draggableWidgets)
	{
		var widget = widgetengine.draggableWidgets[draggableId];
		if(widget != null && widget.ignoresPageScroll)
		{
			widget.move(offsetX, offsetY);
		}
	}
	savedScrollPos = scrollPos;
}

//todo sort out x,y <-> top,left


document.onmouseup = dropWidget;
document.onmousemove = dragWidget;
window.onscroll = scroll;

