/// <reference path="/EasySiteWeb/EasySite/SupportFiles/ExtJS/vswd-ext_1.1.1.js" />

var EasySiteGUI = function () {

	// everything in this space is private and only accessible in the TemplateDesigner block
	var DropLocked = false;
	var CachedDropValidity = { dragId: '', dropId: '', valid: false, Clear: function () { dragId = '', dropId = '', valid = false } };
	var IsLoaded = false;
	var Droppables = [];
	var Draggables = [];
	var SortableConfigs = [];
	var PaletteWindow;
	var State;
	var MouseDown = false;
	var WindowConfigs = [];
	var Windows = [];
	var Sortables = [];
	var StartupActions = [];
	var PalleteWindowOveride;
	var PalleteElementPrefix;
	var RepositionElementPrefix;

	function MaintainToolPalettePositionForIE() {

		// Use javascript to position the tool palette 50px from the top of the screen.
		var windowElement = document.getElementById("TemplateDesignerPalette_Window");
		var shadowElement = windowElement.previousSibling;
		var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);

		windowElement.style.top = scrollTop + 50;
		shadowElement.style.top = scrollTop + 50;
	}

	function Setup() {
		var count;
		var form = document.getElementById('frmMain');

		//Setup state
		State = Ext.state.Manager.setProvider(new Ext.state.CookieProvider());

		//Create the template palette window
		if (document.getElementById('TemplateDesignerPalette_Window')) {
			form.appendChild(document.getElementById('TemplateDesignerPalette_Window'));    //Reposition window in the DOM
			PaletteWindow = new Ext.BasicDialog('TemplateDesignerPalette_Window', {
				closable: false,
				autoTabs: true,
				width: 225,
				height: 200,
				shadow: true,
				minWidth: 225,
				minHeight: 200,
				proxyDrag: true,
				x: 100,
				y: 100,
				tabPosition: "top",
				collapsible: false,
				monitorResize: true,
				constraintoviewport: false
			});
			PaletteWindow.restoreState();
			PaletteWindow.footer.setStyle("font-weight", 'bold');
			PaletteWindow.footer.setHeight(25);
			PaletteWindow.show();

			var isBackEnd = window.__isEasySiteAdmin ? __isEasySiteAdmin() : false;
			var isIe7orOver = Ext.isIE7;

			var applyFixedStyleToToolWindow
				= (Ext.isIE && !isBackEnd && isIe7orOver) // IE only displays correctly in the front end on IE7 and over
				|| (!Ext.isIE); // All other browsers get on fine with the fixed layout in all cases.

			if (applyFixedStyleToToolWindow) {

				var windowElement = document.getElementById("TemplateDesignerPalette_Window");
				var shadowElement = windowElement.previousSibling;

				windowElement.style.position = "fixed";
				shadowElement.style.position = "fixed";
			}
			else // Cases for IE6, and for all other IE's in the back-end.
			{
				if (window.attachEvent) {
					window.attachEvent("onscroll", MaintainToolPalettePositionForIE);
					window.attachEvent("onresize", MaintainToolPalettePositionForIE);
				}
				else {
					window.addEventListener("scroll", MaintainToolPalettePositionForIE, false);
					window.addEventListener("resize", MaintainToolPalettePositionForIE, false);
				}
			}

			// If the pallete window is outside of the visible area (because the restored position is outside of the windows viewport),
			// then set it back to the top.  Otherwise, we might have missing palette windows.
			var paletteTop = PaletteWindow.xy[1];
			var paletteHeight = PaletteWindow.size.height;
			var windowHeight = Ext.isIE ? document.documentElement.clientHeight : window.innerHeight;

			if ((paletteTop + paletteHeight) > windowHeight) {
				PaletteWindow.moveTo(PaletteWindow.xy[0], 100);
			}
		}

		//Loop thru windows and init them
		//for(var count = 0; count < WindowConfigs.length; count++){
		for (var count = WindowConfigs.length - 1; count >= 0; count--) {

			var WindowConfig = WindowConfigs[count];
			var config = WindowConfigs[count].config;

			el = document.getElementById(WindowConfig.el);
			form = document.getElementById('frmMain');
			form.appendChild(el);

			//Create the window
			var basicDialog = new Ext.BasicDialog(el, WindowConfig.config);
			if (typeof (WindowConfig.tabChangeCallback) == "function") {
				basicDialog.getTabs().on("tabchange", WindowConfig.tabChangeCallback);
			}
			Windows[WindowConfig.name] = basicDialog;

			//Check if the pallete window has been created outside of this routine.
			if (PalleteWindowOveride == WindowConfig.name) {
				PaletteWindow = Windows[WindowConfig.name];
			}

			Windows[WindowConfig.name].restoreState();
			if (WindowConfig.showOnLoad) {
				Windows[WindowConfig.name].show();
			}

			//Add the buttons
			Ext.each(WindowConfig.buttons, function (btn) {

				var windowName = WindowConfig.name;
				var postbackOnCancel = WindowConfig.postbackOnCancel;
				var controlIdForPostback = WindowConfig.controlId;

				switch (btn.button) {

					case "cancel":
						Windows[WindowConfig.name].addButton(btn.text, function (e) { Windows[windowName].hide(); if (postbackOnCancel) { __doPostBack(controlIdForPostback, btn.button); } });
						break;

					case "cascade":
						Windows[WindowConfig.name].addButton(btn.text, function (e) { showCascadeOptions(); });
						break;

					default:
						Windows[WindowConfig.name].addButton(btn.text, function (e) { Windows[windowName].hide(); __doPostBack(controlIdForPostback, btn.button); });
						break;
				}
			});

			//Register resize handler
			Windows[WindowConfig.name].on('resize', function (win, width, height) {
				Ext.get('floatingwindowW_' + win.name).dom.value = width;
				Ext.get('floatingwindowH_' + win.name).dom.value = height;
				if (win.postbackonresize) {
					Ext.get('floatingwindowEvent_' + win.name).dom.value = 'Resize';
					__doPostBack(win.el.id, '');
				}
			});

			// Postback visibility maintainance
			if (config.maintainPostbackVisibility) {

				var hiddenFieldId = config.visibilityStateHiddenFieldId;
				Windows[WindowConfig.name].hiddenField = document.getElementById(hiddenFieldId);
				if (Windows[WindowConfig.name].hiddenField != null) {

					Windows[WindowConfig.name].on("show", function (win) { this.hiddenField.value = "1"; });
					Windows[WindowConfig.name].on("beforehide", function (win) { this.hiddenField.value = "0"; });
				}
			}

			// Register Show handler
			Windows[WindowConfig.name].on('show', function (win) {

				if (typeof (WindowConfig.config.onShowCallback) == "function") {
					WindowConfig.config.onShowCallback.call();
				}
			});

			// Register Hide handler
			Windows[WindowConfig.name].on('hide', function (win) {

				if (typeof (WindowConfig.config.onHideCallback) == "function") {
					WindowConfig.config.onHideCallback.call();
				}

				if (win.postbackonclose) {
					Ext.get('floatingwindowEvent_' + win.name).dom.value = 'WinClose';
					__doPostBack(win.el.id, '');
				}
			});

			//Show the window
			Windows[WindowConfig.name].body.dom.style.display = 'block';

		}

		//Loop thru draggables and initialise them
		for (var i in Draggables) {

			if (typeof (Draggables[i]) != "function") {

				MakeDraggable(Draggables[i]);
			}

		}

		//Loop thru droppables and init them
		for (var i in Droppables) {

			if (typeof (Droppables[i]) != "function") {

				MakeDroppable(Droppables[i]);
			}
		}

		//Loop thru sortables and init them
		for (var count = 0; count < SortableConfigs.length; count++) {
			MakeSortable(SortableConfigs[count].name, SortableConfigs[count].src);
		}
	}


	//Make the draggable
	function MakeDraggable(draggable) {

		var draggableElement = document.getElementById(draggable.id);
		if (draggableElement) {

			// Make it draggable
			var el = new Ext.dd.DragSource(draggable.id, { revert: false });

			el.addInvalidHandleType("select"); // important - this stops <select> elements performing a drag, allowing them to be used as drop down lists

			if (draggable.customGroups != undefined && draggable.customGroups.length > 0) {
				//We don't want to be able to just drop it anywhere...
				el.removeFromGroup('default');
				Ext.each(draggable.customGroups.split(','), function (g) {
					el.addToGroup(g);
				});
			} else {
				el.beforeDragEnter = function (target, e, id) {
					//cancel the onDragEnter
					return checkValidDrop(this.id, target.id);
				}

				el.beforeDragOver = function (target, e, id) {
					//cancel the onDragOver
					return checkValidDrop(this.id, target.id);
				}
			}

			el.onBeforeDrag = function (data, evt) {
				DropLocked = false;
			}

			el.afterDragDrop = function (droppable, evt, id) {

				if (DropLocked) return false;

				if (!checkValidDrop(this.id, droppable.id)) return false;

				DropLocked = true;

				var y = "";
				for (var x in el.groups) {
					y += x + " : " + el.groups[x] + "\n";
				}

				var draggableElement = document.getElementById(this.id);
				var droppableElement = document.getElementById(droppable.id);

				var draggableData = draggableElement.getAttribute("data");
				var droppableData = droppableElement.getAttribute("data");

				var draggableConfig = Draggables[this.id];
				var droppableConfig = Droppables[droppable.id];

				var callback = droppableConfig.dropCallback;
				if (callback != null && typeof (callbackallback) == "function" && window.callback) {
					callback.call(this, draggableElement, droppableElement, draggableData, droppableData);
				}

				DropElement(this, droppable);

				if (droppableConfig.autoPostBack) {
					__doPostBack(droppableElement.getAttribute("name"), draggableData + "|!|" + droppableData);
				}
			}

			if (PaletteWindow ? true : false) {

				//Window status bar
				var title = draggableElement.title ? draggableElement.title : '';
				draggableElement.onmouseover = function () { if (!MouseDown) { PaletteWindow.footer.dom.innerHTML = '<strong style="font-weight: bold; color: #000">' + title + '</strong>'; window.status = title; } }
				draggableElement.onmouseout = function () { if (!MouseDown) { PaletteWindow.footer.dom.innerHTML = ''; window.status = ''; } }
				draggableElement.onmousedown = function () { MouseDown = true; }
				draggableElement.onmouseup = function () { MouseDown = false; PaletteWindow.footer.dom.innerHTML = ''; window.status = ''; }
			}
		}
	}

	//Make the droppable
	function MakeDroppable(droppable) {

		if (Ext.get(droppable.id) != null) {

			var el = new Ext.dd.DropTarget(droppable.id, {});

			if (droppable.customGroups.length > 0) {
				//We don't want to be able to just drop it anywhere...
				el.removeFromGroup('default');
				Ext.each(droppable.customGroups.split(','), function (g) {
					el.addToGroup(g);
				});
			}
		}
	}

	//Make a sortable list
	function MakeSortable(name, src) {
		var DragTarget;
		Sortables[name] = {
			Init: function () {
				DragTarget = new Ext.dd.DDTarget(src);

				Ext.each(Ext.get(src).dom.childNodes, function (el) {
					var Li = new Ext.dd.DDProxy(el.id, "PageOrder", {});
					Li.onDrag = function (e) {
						var y = Ext.EventObject.getPageY();
						if (y < this.lastY) {
							this.goingUp = true;
						} else if (y > this.lastY) {
							this.goingUp = false;
						}

						this.lastY = y;
					}

					Li.startDrag = function (x, y) {
						var dragEl = this.getDragEl();
						var clickEl = this.getEl();
						dragEl.innerHTML = clickEl.innerHTML;
						dragEl.style.backgroundColor = '#fff';
					}

					Li.onDragOver = function (e, id) {
						var srcEl = this.getEl();
						var destEl = Ext.get(id).dom;
						if (destEl.nodeName.toLowerCase() == "li") {
							var dstParentEl = destEl.parentNode;

							if (this.goingUp) {
								dstParentEl.insertBefore(srcEl, destEl);
							} else {
								dstParentEl.insertBefore(srcEl, destEl.nextSibling);
							}

							Ext.dd.DragDropMgr.refreshCache({ PageOrder: true })
						}
					}
					Li.endDrag = function (e) {
						var srcEl = this.getEl();
						//srcEl.setXY([0,0]);
					}
				})
			},

			GetOrder: function () {
				var t = "";
				Ext.each(DragTarget.getEl().childNodes, function (el) {
					if (el.nodeName.toLowerCase() == 'li') {
						if (t != "")
							t += ",";
						t += el.id;
					}
				});
				return t;
			}
		}

		Sortables[name].Init();
	}


	//Handle a drop onto a dropzone, either a template item or moving an element from one place to another
	function DropElement(element, position) {
		if (element.id.indexOf("esctl_") != -1) { // An existing element was repositioned
			var DragPos = parseInt(element.id.substr(element.id.lastIndexOf("_") + 1));
			var DropPos = parseInt(position.id.substr(position.id.lastIndexOf("_") + 1));

			// Element id is in the form esctl_CtlId_Draggable_PosIndex. We need the CtlId bit, and that's what this horrible bit of string munging does.
			var ElementId = element.id.substr(element.id.indexOf("_") + 1, (element.id.indexOf("_", element.id.indexOf("_") + 1) - 1) - element.id.indexOf("_"));

			if (DragPos == DropPos || DropPos == (DragPos + 1)) return; // Nothing to do

			var Move = 0;

			if (DropPos < DragPos) {
				Move = 0 - (DragPos - DropPos);
			} else {
				Move = (DropPos - 1) - DragPos;
			}

			document.getElementById('PostbackAction').value = 'ReorderElements';
			document.getElementById('PostbackData').value = ElementId + '|' + Move;
			__doPostBack("", ""); // Replaced "document.forms['frmMain'].submit();" because it does not call the onSubmit() handler.

		} else if (element.id.indexOf("TemplateElement_") != -1) {

			var DropPos = parseInt(position.id.substr(position.id.lastIndexOf("_") + 1));
			var ElementType = element.id.substr(element.id.lastIndexOf("_") + 1);

			document.getElementById('PostbackAction').value = 'InsertElement';
			document.getElementById('PostbackData').value = ElementType + '|' + DropPos;
			__doPostBack("", ""); // Replaced "document.forms['frmMain'].submit();" because it does not call the onSubmit() handler.

		} else if (element.id.indexOf(PalleteElementPrefix) != -1 || element.id.indexOf(RepositionElementPrefix) != -1) {

			if (element.id.indexOf(RepositionElementPrefix) != -1) {
				document.getElementById('PostbackAction').value = 'RepositionElement';
			} else {
				document.getElementById('PostbackAction').value = 'InsertElement';
			}
			document.getElementById('PostbackData').value = element.id + '|' + position.id;
			__doPostBack("", ""); // Replaced "document.forms['frmMain'].submit();" because it does not call the onSubmit() handler.

		}
	}

	function checkValidDrop(dragId, dropId) {

		if (CachedDropValidity.dragId == dragId && CachedDropValidity.dropId == dropId) {
			return CachedDropValidity.valid;
		}
		var validDrop = true;
		var draggedElement = document.getElementById(dragId);
		var dropAreaIdElement = document.getElementById(dropId + "_id");

		//Obtain element identifier for dragged item
		var draggedElementData = draggedElement.getAttribute('data');
		if (!draggedElementData) {
			draggedIdElement = document.getElementById(dragId + "_id");
			if (draggedIdElement) {
				draggedElementData = draggedIdElement.value;
			}
		}

		//check container conditions
		if (draggedElementData) {

			if (!checkDDCondition(draggedElementData, document.getElementById(dropId + "_allowlist"), true)) {
				validDrop = false;
			}

			if (checkDDCondition(draggedElementData, document.getElementById(dropId + "_denylist"), false)) {
				validDrop = false;
			}
		}

		//check container item restrictions
		if (dropAreaIdElement) {

			var dropAreaElementId = dropAreaIdElement.value;

			if (!checkDDCondition(dropAreaElementId, document.getElementById(dragId + "_allowlist"), true)) {
				validDrop = false;
			}

			if (checkDDCondition(dropAreaElementId, document.getElementById(dragId + "_denylist"), false)) {
				validDrop = false;
			}
		}

		CachedDropValidity.dragId = dragId;
		CachedDropValidity.dropId = dropId;
		CachedDropValidity.valid = validDrop;

		return validDrop;
	}

	function checkDDCondition(itemToCheck, ruleElement, defaultValue) {

		if (ruleElement) {
			var validValues = ruleElement.value;
			return validValues.indexOf('_' + itemToCheck + '_') > -1;
		}

		return defaultValue;
	}

	function showCascadeOptions() {
		$("div[id$=pnlCascadeHeading]").toggle();
		$(".cascade").toggle();
		$("div[id$=configContainer]").toggleClass("show-cascade");
	}

	// return a public interface, Items in this interface CANNOT be seen by the rest of the object
	return {

		//Set Pallete Window
		SetPalleteWindow: function (palleteWindowName) {
			PalleteWindowOveride = palleteWindowName;
		},


		//Set Identifier for toolbox elements
		SetPalleteElementPrefix: function (prefix) {
			PalleteElementPrefix = prefix;
		},


		//Set identifier for reorder elements
		SetRepositionElementPrefix: function (prefix) {
			RepositionElementPrefix = prefix;
		},


		//Add a draggable to the GUI
		AddDraggable: function (id, groups) {

			Draggables[id] = { id: id, groups: groups };

			if (IsLoaded) {
				MakeDraggable(Draggables[id]);
			}
		},


		//Add a droppable to the GUI
		AddDroppable: function (src, customGroups) {

			this.AddDroppableAndHandlers(src, customGroups, null, false);
		},


		//Add a droppable to the GUI, including some handlers
		AddDroppableAndHandlers: function (id, customGroups, dropCallback, autoPostBack) {

			Droppables[id] = { id: id, customGroups: customGroups, dropCallback: dropCallback, autoPostBack: autoPostBack };

			if (IsLoaded) {
				MakeDroppable(Droppables[id]);
			}
		},


		//Add a sortable UL / LI schema to the GUI
		AddSortable: function (name, src) {
			if (IsLoaded) {
				MakeSortable(name, src);
			} else {
				//Defer
				SortableConfigs[SortableConfigs.length] = { name: name, src: src };
			}
		},


		AddStartUpAction: function (script) {
			StartupActions[StartupActions.length] = script;
		},


		//Initialise the GUI
		Init: function () {
			window.setTimeout(
				function () {
					//Enable garbage collection
					Ext.enableGarbageCollector = true;
					Ext.enableListenerCollection = true;

					IsLoaded = true;
					Setup();

					//Setoff the editor initialisation
					if (typeof (Editor) == 'object') {
						Editor.Init();
					}

					//Setup window scrollpos handler
					Ext.EventManager.on(document.forms[0], 'submit', function () { SaveWindowScrollPos(); });

					//Perform other startup actions
					Ext.each(StartupActions, function (action) { action(); });
				},
				100
			);
		},


		//Add Window
		AddWindow: function (name, el, config, showOnLoad, postbackOnResize, postbackOnClose, postbackOnCancel, buttons, controlId, tabChangeCallback) {
			WindowConfigs[WindowConfigs.length] = {
				name: name,
				el: el,
				config: config,
				showOnLoad: showOnLoad,
				postbackOnResize: (postbackOnResize ? postbackOnClose : false),
				postbackOnClose: (postbackOnClose ? postbackOnClose : false),
				postbackOnCancel: (postbackOnCancel ? postbackOnCancel : false),
				buttons: buttons,
				controlId: controlId,
				tabChangeCallback: tabChangeCallback
			};
		},


		//Windows
		GetWindow: function (name) {
			return Windows[name];
		},


		//Sortables
		GetSortable: function (name) {
			return Sortables[name];
		},


		//Validation tools
		ValidationTools: {
			//Takes key press event
			PositiveNumber: function (evt) {
				var theEvent = evt || window.event;
				var key = theEvent.keyCode || theEvent.which;
				key = String.fromCharCode(key);
				var regex = /[0-9]|\./;
				if (!regex.test(key)) {
					theEvent.returnValue = false;
					if (theEvent.preventDefault) theEvent.preventDefault();
				}
			}
		}
	};
} ();
	
addOnLoadEvent(EasySiteGUI.Init);
