﻿Array.prototype.remove = function(from, to)
{
	var rest = this.slice((to || from) + 1 || this.length);
	this.length = from < 0 ? this.length + from : from;
	return this.push.apply(this, rest);
};

var eventCommands = [];

var UIManager = new Class(
{
	initialize: function()
	{
		this.resizeHandlers = [];
		this.cleanupHandlers = [];
		this.controlRemovalHandlerList = [];
		this.controlRemovalHandlers = {};
		this.elementRemovalHandlers = {};

		this.viewStateHandlerList = [];
		this.viewStateHandlers = {};

		this.commandHandlerList = [];
		this.commandHandlers = {};

		this.initCommands = [];

		this.attachedDialogState = '';
		this.targetDialog = '';

		this.onSetDialog = function() { };
		this.onReceiveModalPopup = function() { };

		this.onBeforeRequest = function() { };
		this.onAfterRequest = function() { };
	},

	registerResizeHandler: function(handler)
	{
		this.resizeHandlers.push(handler);
	},

	registerCleanupHandler: function(handler)
	{
		this.cleanupHandlers.push(handler);
	},

	registerControlRemovalHandler: function(typeID, handler)
	{
		this.controlRemovalHandlerList.push(typeID);
		this.controlRemovalHandlers[typeID] = handler;

		ui.elementRemovalHandlers[typeID] = handler;
	},

	registerViewStateHandler: function(typeID, handler)
	{
		this.viewStateHandlerList.push(typeID);
		this.viewStateHandlers[typeID] = handler;
	},

	registerCommandHandler: function(action, handler)
	{
		this.commandHandlerList.push(action);
		this.commandHandlers[action] = handler;
	},

	getNestedControl: function(el, id)
	{
		return $(el).getElement("[id=" + id + "]");
	},

	getSubElement: function(el, id)
	{
		return $(el).getElement("[id=" + id + "]");
	},

	getDialogParameters: function(dialog)
	{
		var dlgParameters = $(dialog.id + "_parameters");

		if (dlgParameters != null)
		{
			return dlgParameters.value;
		}

		return "{}";
	},

	collectDialogState: function(dialog)
	{
		if (dialog == null)
		{
			return {};
		}

		return {
			"DialogID": dialog.id,
			"DialogState": ui.collectViewState(dialog, true),
			"DialogParameters": base64Json.decode(ui.getDialogParameters(dialog))
		}
	},

	getMetaElements: function(dialog)
	{
		var dialogElements = $(dialog.id + "_elements");
		var metaElements = [];

		if (dialogElements != null && dialogElements.value != "")
		{
			var elements = dialogElements.value.split(",");

			for (var i = 0; i < elements.length; i++)
			{
				var dialogElement = elements[i].split(":");

				var metaElement =
				{
					ID: dialogElement[0],
					TypeID: dialogElement[1],
					Control: null
				};

				metaElement.Control = ui.getSubElement(dialog, metaElement.ID);

				metaElements.push(metaElement);
			}
		}

		return metaElements;
	},

	collectViewState: function(dialog, collectSubStates)
	{
		var controlStates = {};

		controlStates["__type"] = "cs";

		if (dialog == null)
		{
			return controlStates;
		}

		var metaElements = ui.getMetaElements(dialog);

		for (var i = 0; i < metaElements.length; i++)
		{
			var metaElement = metaElements[i];

			if (ui.viewStateHandlerList.contains(metaElement.TypeID))
			{
				if (metaElement.Control != null)
				{
					controlStates[metaElement.ID] = ui.viewStateHandlers[metaElement.TypeID](metaElement.Control);
				}
			}
		}

		return controlStates;
	},

	attachDialogState: function(dialogID)
	{
		this.attachedDialogState = base64Json.encode(this.collectDialogState($(dialogID)));
	},

	overwriteDialogTarget: function(dialogID)
	{
		this.targetDialog = dialogID;
	},

	executeAction: function(dialogID, actionID, actionParams)
	{
		if (this.onBeforeRequest != null)
		{
			this.onBeforeRequest();
		}

		var actionParams = { "dialogID": dialogID, "actionID": actionID, "actionParams": actionParams };
		var actionParamsJSON = JSON.encode(actionParams);

		var reqAction = new Request(
		{
			url: "/UIService.asmx/ExecuteAction",
			urlEncoded: false,
			method: "post",
			data: actionParamsJSON,
			headers: { "Content-Type": "application/json; charset=utf-8", "Accept": "application/json" },
			onSuccess: function(retVal)
			{
				var commands = JSON.decode(retVal)["d"];
				ui.processCommands(commands);
			}
		});

		reqAction.send();
	},

	handleEvent: function(dialogID, sender, eventName)
	{
		//stateHistory.states[stateHistory.position] = site.buildState();

		if (this.targetDialog != '')
		{
			dialogID = this.targetDialog;
			this.targetDialog = '';
		}

		var dialog = $(dialogID);

		if (dialog == null)
		{
			alert("Could not find dialog '" + dialogID + "'");
			return;
		}

		var viewState = base64Json.encode(this.collectViewState(dialog, false));
		var parameters = $(dialogID + "_parameters").value;

		if (this.onBeforeRequest != null)
		{
			this.onBeforeRequest();
		}

		var eventParams = { "dialogID": dialogID, "dialogParams": parameters, "dialogState": viewState, "controlID": sender.id, "eventName": eventName, "siteState": this.attachedDialogState };
		var eventParamsJSON = JSON.encode(eventParams);

		// NOTE: Create reqEvents earlier and just change the data - reduce overhead
		var reqEvent = new Request(
		{
			url: "/UIService.asmx/HandleEvent",
			urlEncoded: false,
			method: "post",
			data: eventParamsJSON,
			headers: { "Content-Type": "application/json; charset=utf-8", "Accept": "application/json" },
			onSuccess: function(retVal)
			{
				var commands = JSON.decode(retVal)["d"];
				ui.processCommands(commands);
			}
		});

		reqEvent.send();

		//UIService.HandleEvent(dialogID, parameters, viewState, sender.id, eventName, this.attachedDialogState, this.processCommands);
		this.attachedDialogState = '';
	},

	load: function()
	{
		try
		{
			this.processCommands(this.initCommands);
		}
		catch (e)
		{

		}

		window.onresize = function()
		{
			ui.onResize();
		}

		ui.onResize();
	},

	executeHandlers: function(handlers, args)
	{
		for (var i = 0; i < handlers.length; i++)
		{
			var handler = handlers[i];

			if (handler != null)
			{
				try
				{
					handler(args);
				}
				catch (e)
				{

				}
			}
		}
	},

	onResize: function()
	{
		ui.executeHandlers(ui.resizeHandlers);
	},

	cleanupElement: function(rootElement)
	{
		ui.executeHandlers(ui.cleanupHandlers, rootElement);

		rootElement.empty();
	},

	invokeClientMethod: function(data)
	{
		var obj = window[data["o"]];

		if ($defined(obj))
		{
			var method = obj[data["m"]];

			if ($defined(method)) // && $type(method) == 'function'
			{
				method.run(data["p"]);
			}
		}
	},

	processCommand: function(command)
	{
		var data = command.Data;

		if (ui.commandHandlerList.contains(command.Action))
		{
			ui.commandHandlers[command.Action](command);
		}
		else
		{
			switch (command.Action)
			{
				case "updateParameters":
					var dialogParams = $(data.DialogID + "_parameters");

					if (dialogParams != null)
					{
						$(data.DialogID + "_parameters").value = data.Parameters;
					}

					break;
				case "addClientStyle":
					if (Browser.Engine.trident)
					{
						var styleSheet = document.styleSheets[document.styleSheets.length - 1];
						styleSheet.addRule(data.Selector, data.Style, -1)
					}
					else
					{
						var styleSheet = document.styleSheets[document.styleSheets.length - 1];
						var cssRule = data.Selector + " {" + data.Style + "}";
						styleSheet.insertRule(cssRule, styleSheet.cssRules.length - 1)
					}

					break;
				case "redirect":
					document.location.href = data.Url;
					break;
				case "eval":
					eval(data.Script);
					break;
				case "setDialog":
					var pnlContainer = null;

					if (data.ShowAsMP == true)
					{
						pnlContainer = $("mpDialogInner");
					}
					else
					{
						pnlContainer = $(data.Container);
					}

					if (pnlContainer == null)
					{
						break;
					}

					ui.cleanupElement(pnlContainer);

					var mp = $("mp");
					var mpDialog = $("mpDialog");

					mp.setOpacity(0.0);
					mp.setStyles({ display: "block" });

					mpDialog.setOpacity(0.0);
					mpDialog.setStyles({ display: "block" });

					pnlContainer.set("html", data.Dialog);

					var elDialog = pnlContainer.getFirst();

					if (elDialog != null)
					{
						uiDialog.init(elDialog, data.clientData);
					}

					//alert(JSON.encode(data.InitCommands));

					if (data.InitCommands && data.InitCommands.length > 0)
					{
						ui.processSubCommands(data.InitCommands);
					}

					if (data.ShowAsMP == true)
					{
						//						if (data.MPWidth != -1)
						//						{
						//							pnlContainer.set("width", data.MPWidth);
						//						}

						if (ui.onReceiveModalPopup != null)
						{
							ui.onReceiveModalPopup();
						}
					}

					window.scrollTo(0, 0);

					if (ui.onSetDialog != null)
					{
						ui.onSetDialog();
					}

					break;
				case "initDialog":
					var elDialog = $(data["_d"]);

					if (elDialog != null)
					{
						uiDialog.init(elDialog, data["_c"]);
					}

					break;
				case "deleteDialog":
					var container = $(data.Container);

					if (container == null)
					{
						break;
					}

					ui.cleanupElement(container);

					break;
				case "setUIProp":
					var el = ui.getSubElement(data.dialogID, data.controlID);

					if (el == null)
					{
						break;
					}

					el.set(data.key, data.value);

					break;
				case "invoke":
					ui.invokeClientMethod(data);
					break;
			}
		}
	},

	processSubCommands: function(subCommands, onFinish)
	{
		if (!subCommands)
		{
			return;
		}

		for (var i = 0; i < subCommands.length; i++)
		{
			try
			{
				ui.processCommand(subCommands[i]);
			}
			catch (e)
			{

			}
		}

		return true;
	},

	processCommands: function(commands, onFinish)
	{
		eventCommands = commands;

		if (!commands)
		{
			return;
		}

		for (var i = 0; i < commands.length; i++)
		{
			try
			{
				ui.processCommand(commands[i]);
			}
			catch (e)
			{

			}
		}

		if (ui.onAfterRequest != null)
		{
			ui.onAfterRequest();
		}

		ui.onResize();

		return true;
	}
});

var ui = new UIManager();
