﻿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 UIManager = new Class(
{
	initialize : function()
	{
		this._cells = [];

		this._dialogRendererList = [];
		this._dialogRenderer = { };

		this._viewStateHandlerList = [];
		this._viewStateHandlers = { };

		this._initCommands = [];
		this._smartPadding = 10;

		this._attachedDialogState = '';
		this._targetDialog = '';

		this.onUpdateDialog = function() { };
		this.onReceiveModalPopup = function() { };

		this.onBeforeRequest = function() { };
		this.onAfterRequest = function() { };
	},

	registerDialogRenderer : function(renderer, handler)
	{
		this._dialogRendererList.push(renderer);
		this._dialogRenderer[renderer] = handler;
	},

	registerViewStateHandler : function(typeID, handler)
	{
		this._viewStateHandlerList.push(typeID);
		this._viewStateHandlers[typeID] = handler;
	},
	
	getNestedControl : function(control, controlID)
	{
		return $(control).getElement("[id='" + controlID + "']");
	},

	collectDialogState : function(dialog)
	{
		if (dialog == null)
		{
			return { };
		}

		return {
			"DialogID" : dialog.id,
			"DialogTypeID" : dialog.getProperty("typeid"),
			"DialogState" : ui.collectViewState(dialog, true),
			"DialogParameters" : base64Json.decode($(dialog.id + "_parameters").value)
		}
	},

	collectViewState : function(dialog, collectSubStates)
	{
		var controlStates = { };

		controlStates["__type"] = "cs";

		if (dialog == null)
		{
			return controlStates;
		}

		var metaControls = $(dialog.id + "_controls");

		if (metaControls.value != "")
		{
			var controls = metaControls.value.split(",");

			for (var i = 0; i < controls.length; i++)
			{
				var metaControl = controls[i].split(":");

				var metaControlID = metaControl[0];
				var metaControlTypeID = metaControl[1];

				if (!this._viewStateHandlerList.contains(metaControlTypeID))
				{
					continue;
				}

				var control = this.getNestedControl(dialog, metaControlID);

				if (control != null)
				{
					controlStates[metaControlID] = this._viewStateHandlers[metaControlTypeID](control);
				}
			}
		}

		if (collectSubStates == true)
		{
			var metaDialogs = $(dialog.id + "_dialogs");

			if (metaDialogs.value != "")
			{
				var dialogs = metaDialogs.value.split(",");

				for (var i = 0; i < dialogs.length; i++)
				{
					var dialogState = ui.collectViewState($(dialogs[i]), true);

					var temp = {};

					temp["__type"] = "vs";
					temp["State"] = dialogState;
					temp["Parameters"] = base64Json.decode($(dialogs[i] + "_parameters").value);

					controlStates[dialogs[i]] = temp;
				}
			}
		}

		return controlStates;
	},

	attachDialogState : function(dialogID)
	{
		this._attachedDialogState = base64Json.encode(this.collectDialogState($(dialogID)));
	},

	overwriteDialogTarget : function(dialogID)
	{
		this._targetDialog = dialogID;
	},

	handleEvent : function(dialogID, sender, eventName)
	{
		stateHistory.states[stateHistory.position] = buildLifeState();

		if (this._targetDialog != '')
		{
			dialogID = this._targetDialog;
			this._targetDialog = '';
		}
		
		var dialog = $(dialogID);

		if (dialog == null)
		{
			alert("Could not find dialog '" + dialogID + "'");
			return;
		}

		var dialogTypeID = dialog.getProperty("typeid");
		var viewState = base64Json.encode(this.collectViewState(dialog, false));
		var parameters = $(dialogID + "_parameters").value;

		if (this.onBeforeRequest != null)
		{
			this.onBeforeRequest();
		}

		UIService.HandleEvent(dialogID, dialogTypeID, parameters, viewState, sender.id, eventName, this._attachedDialogState, this.processCommands);
		this._attachedDialogState = '';
	},

	load : function()
	{
		if (this._cells.length > 0)
		{
			this.loadCells(null, this._cells);
		}

		this.processCommands(this._initCommands);
	},

	processCommands : function(commands, onFinish)
	{
		for (var i = 0; i < commands.length; i++)
		{
			var command = commands[i];
			var data = command.Data;

			switch (command.Action)
			{
				case "update":
					var isModalPopup = data.IsModalPopup;
					var ajaxPanel = null;

					if (isModalPopup == true)
					{
						ajaxPanel = $("mpDialogInner");
					}
					else
					{
						ajaxPanel = $(data.AjaxPanel);
					}

					if (ajaxPanel == null)
					{
						alert("Could not find ajax panel to update");
						return;
					}

					ajaxPanel.setHTML(data.Content);

					if (data.ResetScroll == true)
					{
						window.scrollTo(0,0);
					}
				
					if (ui.onUpdateDialog != null)
					{
						ui.onUpdateDialog();
					}

					if (isModalPopup == true)
					{
						if (ui.onReceiveModalPopup != null)
						{
							ui.onReceiveModalPopup();
						}
					}

					break;
				case "redirect":
					document.location.href = data.Url;
					break;
				case "eval":
					eval(data.Script);
					break;
			}
		}

		if (onFinish != null)
		{
			onFinish();
		}

		if (ui.onAfterRequest != null)
		{
			ui.onAfterRequest();
		}
	},

	resizeDialog : function(cell, cellDiv)
	{
		if (cell.Dialog == null)
		{
			return;
		}

		if (this._dialogRendererList.contains(cell.Dialog.Renderer))
		{
			this._dialogRenderer[cell.Dialog.Renderer].resizeDialog(cell, cellDiv);
		}
	},

	calculateCellSize : function(cell, parentSize, usedWidth, usedHeight)
	{
		switch (cell.Kind)
		{
			// Column
			case 0:
				switch (cell.Unit)
				{
					// Pixel
					case 0:
						cellWidth = cell.Width;
						break;

					// Percent
					case 1:
						cellWidth = parentSize.x * (cell.Width / 100);
						break;

					// Fill
					case 2:
						cellWidth = (parentSize.x - usedWidth) * cell.Width;
						break;
				}

				cellHeight = parentSize.y;			

				break;

			// Row
			case 1:
				switch (cell.Unit)
				{
					// Pixel
					case 0:
						cellHeight = cell.Height;
						break;

					// Percent
					case 1:
						cellHeight = parentSize.y * (cell.Height / 100);
						break;

					// Fill
					case 2:
						cellHeight = (parentSize.y - usedHeight) * cell.Height;
						break;
				}

				cellWidth = parentSize.x;

				break;

			// Cell
			case 2:
				cellWidth = parentSize.x;
				cellHeight = parentSize.y;

				break;
		}

		return { x : cellWidth, y : cellHeight };
	},

	resizeCells : function(parentElement, cells)
	{
		if (cells.length == 0)
		{
			return;
		}

		var cellKind = cells[0].Kind;

		var cellSizes = [];

		var parentSize = parentElement.getSize();
		var usedWidth = 0;
		var usedHeight = 0;

		switch (cellKind)
		{
			case 0:
				usedWidth = (cells.length - 1) * this._smartPadding;
				break;
			case 1:
				usedHeight = (cells.length - 1) * this._smartPadding;
				break;
		}

		// Get fixed cell sizes
		for (var i = 0; i < cells.length; i++)
		{
			var cell = cells[i];

			if (cell.Unit == 2) continue;

			var cellSize = this.calculateCellSize(cell, parentSize, usedWidth, usedHeight);

			switch (cell.Kind)
			{
				case 0:
					usedWidth += cellSize.x;
					break;
				case 1:
					usedHeight += cellSize.y;
					break;
			}

			cellSizes[i] = cellSize;
		}

		// Get dynamic cell sizes
		for (var d = 0; d < cells.length; d++)
		{
			var dynamicCell = cells[d];

			if (dynamicCell.Unit != 2) continue;

			var dynamicCellSize = this.calculateCellSize(dynamicCell, parentSize, usedWidth, usedHeight);

			cellSizes[d] = dynamicCellSize;
		}

		var left = 0;
		var top = 0;

		// Resize and position cells
		for (var c = 0; c < cells.length; c++)
		{
			var cell = cells[c];
			var cellSize = cellSizes[c];

			var cellPadding = this._smartPadding;

			if (c == cell.length-1)
			{
				cellPadding = 0;
			}

			var cellDiv = $(cell.ID);

			cellDiv.setStyle("left", left);
			cellDiv.setStyle("top", top);
			cellDiv.setStyle("width", cellSize.x);
			cellDiv.setStyle("height", cellSize.y);

			switch (cell.Kind)
			{
				case 0:
					left += cellSize.x + cellPadding;
					break;
				case 1:
					top += cellSize.y + cellPadding;
					break;
			}

			this.resizeDialog(cell, cellDiv);

			if (cell.ChildNodes.length > 0)
			{
				this.resizeCells(cellDiv, cell.ChildNodes);
			}
		}
	},

	populateCells : function(parentElement, cells)
	{
		parentElement.empty();

		for (var i = 0; i < cells.length; i++)
		{
			var cell = cells[i];

			var cellDiv = new Element("div", { "id": cell.ID } );

			cellDiv.addClass("cell");

			cellDiv.setStyle("background-color", cell.Color);
			cellDiv.setStyle("background-color", "#FFFFFF");

			if (cell.ChildNodes.length > 0)
			{
				this.populateCells(cellDiv, cell.ChildNodes);
			}
			else if (cell.Dialog != null)
			{
				if (this._dialogRendererList.contains(cell.Dialog.Renderer))
				{
					this._dialogRenderer[cell.Dialog.Renderer].renderDialog(cell, cellDiv);
				}
				else
				{
					cellDiv.innerHTML = cell.Dialog.Content;
				}
			}

			parentElement.adopt(cellDiv);
		}
	},

	loadCells : function(parentCell, cells)
	{
		if (parentCell == null)
		{
			parentCell = { ID : "grid", ChildNodes : [] };
		}

		var cellDiv = $(parentCell.ID);

		this.filterCells(cells);

		this.populateCells(cellDiv, cells);

		this.resizeCells(cellDiv, cells);

		parentCell.ChildNodes = cells;

		if (parentCell.ID == "grid")
		{
			this._cells = cells;
		}
	},

	getCellByID : function(cellID, cells)
	{
		var cell = null;

		for (var i = 0; i < cells.length; i++)
		{
			if (cells[i].ID == cellID)
			{
				cell = cells[i];
				break;
			}

			if (cells[i].ChildNodes.length > 0)
			{
				cell = this.getCellByID(cellID, cells[i].ChildNodes);
				if (cell != null)
				{
					break;
				}
			}
		}

		return cell;
	}
});

var uiManager = new UIManager();
var ui = uiManager;

function HandleEvent(dialogID, sender, eventName)
{
	uiManager.handleEvent(dialogID, sender, eventName);
}