var Server =
{
	Call: function(destID, method, arg)
	{
		Server.CallMulti([{destID:destID, method:method, arg:arg}]);
	},

	CallMulti: function(actions)
	{
		if (!actions || !actions.length)
		{
			return;
		}

		if (actions.detect(function(action)
		{
			return action.client;
		}))
		{
			actions.each(function(action, index)
			{
				Widget.GetByID(action.destID)[action.method](action.arg);
			});
		}
		else
		{
			var parameters = actions.collect(function(action, index)
			{
				var query = '__actions[' + index + '][destID]=' + escape(action.destID) + '&__actions[' + index + '][method]=' + escape(action.method);

				if (action.arg)
				{
					for (var name in action.arg)
					{
						query += '&__actions[' + index + '][arg][' + escape(name) + ']=' + escape(action.arg[name]);
					}
				}
				else
				{
					query += '&__actions[' + index + '][arg]=';
				}

				return query;
			}).join('&');

			parameters += '&' + BaseKit.SerializeWidgets();

			var options =
			{
				method: 'post',
				parameters: parameters,
				onComplete: function(request)
				{
					try
					{
//						alert(request.responseText);
						eval(request.responseText);
					}
					catch(e)
					{
						alert(request.responseText);
					}
				}
			}

//			alert(options.parameters);

			new Ajax.Request(location.href, options);
		}
	}
};

var BaseKit =
{
	Start: function()
	{
		// TODO: ActiveX control activation
	},

	SerializeWidgets: function()
	{
		var query = Widget.__all.collect(function(widget, index)
		{
			var query = widget.serialize();

			if (!query)
			{
				throw $continue;
			}

			return query;
		});

		return query.join('&');
	},

	Action: function(actions)
	{
		if (!actions)
		{
			return;
		}

		Server.CallMulti(actions);
	}
};

BaseKit.Tools =
{
	HideSelects: function()
	{
		$A(document.body.getElementsByTagName('select')).each(function(element)
		{
			Element.setStyle(element, {visibility:'hidden'});
		});
	},

	ShowSelects: function()
	{
		$A(document.body.getElementsByTagName('select')).each(function(element)
		{
			Element.setStyle(element, {visibility:'visible'});
		});
	},

	EnableInputs: function()
	{
		$A(document.body.getElementsByTagName('input')).each(function(element)
		{
			element.disabled = false;
		});
	},

	DisableInputs: function()
	{
		$A(document.body.getElementsByTagName('input')).each(function(element)
		{
			element.disabled = true;
		});
	},

	EnableButtons: function()
	{
		$A(document.body.getElementsByTagName('button')).each(function(element)
		{
			element.disabled = false;
		});
	},

	DisableButtons: function()
	{
		$A(document.body.getElementsByTagName('button')).each(function(element)
		{
			element.disabled = true;
		});
	}
};

var Widget =
{
	Create: function(type, extend)
	{
		if (Widget[type])
		{
			alert('ERROR (Widget.Install): Widget ' + type + ' already exists');
		}

		Widget[type] = function()
		{
			if (this.__construct)
			{
				this.__construct.apply(this, arguments);
			}
		};

		if (extend)
		{
			Object.extend(Widget[type].prototype, Object.extend(Widget.Base.prototype, extend));
		}
		else
		{
			Object.extend(Widget[type].prototype, Widget.Base.prototype);
		}
	},

	Uninstall: function(id)
	{
		for (var i = 0; i < Widget.__all.length; i++)
		{
			if (Widget.__all[i].id == id)
			{
				Widget.__all[i].destruct();
				delete Widget.__all[i];
				Widget.__all.splice(i, 1);
			}
		}
	},

	GetByID: function(id)
	{
		var detected = $A(Widget.__all).detect(function(widget)
		{
			if (widget.id == id)
			{
				return widget;
			}
		});

		if (!detected)
		{
			alert('ERROR (Widget.GetByID): Widget ' + id + ' not found');
		}

		return detected;
	}
};

Widget.__all = new Array();

Widget.Base = {};

Widget.Base.prototype =
{
	__construct: function(props, exported, events)
	{
		Widget.__all.push(this);

		this.__events = events;

		for (var name in events)
		{
			eval('if(!this.' + name + '){this.' + name + '=function(){Server.CallMulti(this.__events.' + name + ');}}');
		}

		exported.each(function(name)
		{
			eval("if (!this." + name + "){this." + name + "=function(arg){Server.Call(this.getID(),'" + name + "',arg);}}");
		}.bind(this));

		for (var name in props)
		{
			this[name] = props[name];
		}

		this.construct();
	},

	construct: function()
	{
	},

	destruct: function()
	{
	},

	serialize: function()
	{
		return null;
	},

	getID: function(element)
	{
		if (element && element.length)
		{
			return this.id + ':' + element;
		}
		else
		{
			return this.id;
		}
	},

	getParent: function()
	{
		if (typeof this.parent != 'string')
		{
			alert('ERROR (Widget.Base.getParent): Widget ' + this.getID() + ' does not have a parent');
		}

		return Widget.GetByID(this.parent);
	},

	getChild: function(name)
	{
		return Widget.GetByID(this.getID(name));
	},

	observe: function(name, element, event)
	{
		if (!element)
		{
			element = $(this.getID());
		}

		if (!event)
		{
			event = name.toLowerCase();
		}

		if (this[name])
		{
			Event.observe(element, event, this[name].bindAsEventListener(this));
		}
	}
};
