 
// reference local blank image
Ext.BLANK_IMAGE_URL = 'scripts/ext-2.0/resources/images/default/s.gif';
 
// create namespace
Ext.namespace('PersonalHomePage');
 
// create application
PersonalHomePage = function() {
	//private space
	var portletRegister = {};
	var portlets = [];
	var columns = [];
	var ready = false;
	var hasMenu = false;
	var userId = 0;
	var articleId = 0;
	var partScripts = false;
	var state = {};
	var baseUrl = 'index.aspx?articleid=';
	var delimiter = '&';
	var savedListener = null;

	// Add the portlet 'aportlet' to either the menu or the column in 'acolumn' depending on whether the aportlet's 
	// displayed property is 'C' (Closed) or not.
	function addPortlet(acolumn, aportlet, loadcontents, isInitialLoad) {
		if (aportlet.v == 'C' || acolumn == null) {
			// This item is in the menu
			addToMenu(aportlet);
		} else {
			// This item is being added to the display. Ascertain which tools the portlet needs
			portletTools = [];
			if (aportlet.edit) {
				findTool(portletTools, 'edit');
			}
			if (aportlet.close) {
				findTool(portletTools, 'close');
			}

			// Add the panel to the column
			var portletConfig = {
				title: aportlet.ttl,
				autoWidth: true,
				id: 'p' + aportlet.uid,
				tools: portletTools,
				stateEvents: ["drop", "close", "collapse", "expand"],
				draggable: aportlet.drag,
				collapsible: aportlet.min,
				collapsed: aportlet.ismin,
				cls: aportlet.cls,
				partId: aportlet.aid,
				style: "padding-bottom: 5px;",
				bodyStyle: aportlet.s
			}
			// Only load the innards if we've been asked to
			if (loadcontents) {
				portletConfig.autoLoad = {
					url: createUrl(aportlet, false, articleId),
					scripts: partScripts,
					callback: function(el, success, response, options) {
						iCM.PersonalHomePage.FixLinks(el.dom, '_blank', this.fixAnchors);
						if (aportlet.ht && aportlet.ht > 0) {
							innards = el.child('div');
							if (innards) {
								innards.dom.style.height = aportlet.ht + 'px';
								innards.dom.style.overflowY = 'scroll';
							}
						}
					}
				}
			}

			var newRowIdx = hasMenu && aportlet.c == columns.length - 1 ? aportlet.r + 1 : aportlet.r;
			var portletPanel = isInitialLoad ? acolumn.add(portletConfig) : acolumn.insert(newRowIdx, portletConfig);

			// Listen to minimize/maximize events
			portletPanel.addListener('expand', expand);
			portletPanel.addListener('collapse', collapse);

			// Link the newly created gui panel to the original definition
			aportlet.panel = portletPanel;
			portletPanel.portlet = aportlet;
		}
	};

	// Add the portlet 'aportlet' to the menu panel, and set it's status to be (C)losed
	function addToMenu(aportlet) {
		portletTools = [];
		if (aportlet.edit) {
			findTool(portletTools, 'edit');
		}
		if (aportlet.close) {
			findTool(portletTools, 'close');
		}
		aportlet.v = 'C';
		var menu = Ext.getCmp('portletMenu');
		var panel = menu.add({
			title: aportlet.ttl,
			tools: portletTools,
			draggable: true,
			collapsible: true,
			collapsed: true,
			stateEvents: ["drop", "close", "collapse", "expand"],
			id: 'm' + aportlet.uid
		});
		panel.portlet = aportlet;
		menu.doLayout();

		// Update subscriptions or cookies
		updateUser(aportlet);
	};

	// Adjust parts within column after a part has moved
	function adjust(data, oldColIndex, oldIndex, portlet, checkPrevious) {
		partsToMove = [];

		// Build items to move down
		try {
			for (var i = 0; i < data.items.length; i++) {
				var thisPortlet = data.items[i];
				if (thisPortlet != portlet && thisPortlet.c == portlet.c && thisPortlet.r >= portlet.r && thisPortlet.v == 'V') {
					thisPortlet.r++;
					partsToMove.push(thisPortlet);
				}
			}

			// Build items to move up
			if (checkPrevious) {
				for (var i = 0; i < data.items.length; i++) {
					var thisPortlet = data.items[i];
					if (thisPortlet != portlet && thisPortlet.c == oldColIndex && thisPortlet.r >= oldIndex && thisPortlet.r > 0 && thisPortlet.v == 'V') {
						thisPortlet.r--;
						partsToMove.push(thisPortlet);
					}
				}
			}

			// Move the items
			for (var i = 0; partsToMove.length; i++) {
				updateUser(partsToMove[i]);
			}
		}
		catch (err) {
			if (err) {
			}
		}
	}

	// Panel has been collapsed
	function collapse(e) {
		resize(e.portlet, true);
	};

	// Create a simple url
	function createUrl(aportlet, isedit, homepageId) {
		url = baseUrl + aportlet.aid + delimiter + 'homepageid=' + homepageId + '&editmode=' + isedit + '&objectid=' + aportlet.oid
			+ '&sequence=' + aportlet.seq + '&ref=' + new Date().getTime();
		return url;
	};

	// Debug message
	function debug(msg) {
		try {
			if (!document.all && console) {
				console.log(msg);
			}
		} catch (err) { }
	}

	// Enable automatic scrolling of parts
	function enableScrolling() {
		for (var id in portletRegister) {
			var portlet = portletRegister[id];
			if (portlet.panel && portlet.panel.dd && !portlet.panel.dd.scroll) {
				portlet.panel.dd.scroll = true;
			}
		}
	}

	// Panel has been expanded
	function expand(e) {
		resize(e.portlet, false);
	};

	// Find the tool with the id of 'toolname' in the 'parttools' array of objects
	function findTool(parttools, toolName) {
		var thetool = null;
		for (i = 0; i < tools.length && !thetool; i++) {
			if (tools[i].id == toolName) {
				thetool = tools[i];
			}
		}
		if (thetool) {
			parttools.push(thetool);
		}
	};

	// Find a portlet by it's unique Id
	function getPortlet(id) {
		return portletRegister[id];
	};

	// Find a portlet by it's object Id
	function getPortletByObjectId(id) {
		return portletRegister['o' + id];
	}

	// Register a portlet
	function registerPortlet(portlet) {
		debug('Register portlet: ' + portlet.uid + '. article #' + portlet.aid + ' (' + portlet.ttl + '), object id #' + portlet.oid + ', visibility: ' + portlet.v);
		portletRegister[portlet.uid] = portlet;
		portletRegister['o' + portlet.oid] = portlet;
	};

	// Resize a portlet
	function resize(portlet, minimize) {
		portlet.ismin = minimize;
		updateUser(portlet);
	};

	// Unregister a portlet
	function unregisterPortlet(portlet) {
		debug('Unregister portlet: ' + portlet.uid + ' (' + portlet.ttl + ')');
		delete portletRegister[portlet.uid];
		delete portletRegister['o' + portlet.oid];
	};

	// Ask the designated state listener class to update the details of the supplied portlet
	function updateUser(portlet, callback) {
		// Obj id, user id, article id, part id, sequence, minimized, display status, column, row, extra data
		if (ready) {
			debug('Updating: ' + portlet.uid + ', Object Id:' + portlet.oid +
				', Part:' + portlet.aid + ', Sequence:' + portlet.seq +
				', Minimized:' + portlet.ismin + ', Status:' + portlet.v +
				', Column: ' + portlet.c + ', Row: ' + portlet.r);

			// Article Id, portlet, ok_Callback, failed_callback
			savedListener.Update(articleId, portlet,
				function(target, response) {
					// Successful RPC call notification
					if (response) {
						portlet.oid = response.result;
						registerPortlet(portlet);
						debug('Object Id/Sequence: ' + response.result);
						if (callback != null) {
							callback();
						}
					}
				},
				function(status) {
					// Notification that the RPC call failed
					debug('Failed to update portlet. Status code: ' + status);
				}
			);
		}
	};

	return {
		// public methods

		// Create a new part based upon the portlet id and add it to the home page. This method is called by the Part Browser
		Add: function(uniqueid) {
			var portlet = getPortlet(uniqueid);
			if (portlet) {
				var portletClone = {}
				for (key in portlet) {
					portletClone[key] = portlet[key];
				}
				portletClone.v = 'V';
				portletClone.reuse = true;
				portletClone.panel = null;
				portletClone.oid = 0;
				portletClone.ismin = false;
				portletClone.extra = '';

				// Set new sequence number + unique id
				usedSequences = {};
				for (id in portletRegister) {
					if (portletRegister[id] && portletRegister[id].aid == portlet.aid) {
						usedSequences[portletRegister[id].seq] = 'x';
					}
				}
				done = false;
				portletClone.seq = 1;
				for (newseq = 1; newseq < 200 && !done; newseq++) {
					if (!usedSequences[newseq]) {
						portletClone.seq = newseq;
						done = true;
					}
				}
				portletClone.uid = '' + portletClone.aid + portletClone.seq;

				// Add to state object
				state.items.push(portletClone);

				// Set index of new addition in column
				portletClone.r = 0;

				var column = columns[portletClone.c];
				if (column) {
					addPortlet(column, portletClone, false, false);
					updateUser(portletClone,
						function() {
							// Load the contents of the newly created panel
							portletClone.panel.load({
								url: createUrl(portletClone, true, articleId),
								scripts: partScripts,
								callback: function(el, success, response, options) {
									iCM.PersonalHomePage.FixLinks(el.dom, '_blank');
								}
							});
						}
					);
					adjust(state, 0, 0, portletClone, false);
					draggable.doLayout();
					if (iCM.PersonalHomePagePartBrowser) {
						iCM.PersonalHomePagePartBrowser.Refresh();
					}
				}
			}
		},

		// Build the display
		BuildDisplay: function(target, data, fixLinks, stateListener) {
			// Hide display area while building
			Ext.get(target).dom.style.display = 'none';

			savedListener = stateListener;
			state = data;
			hasMenu = (data.closestrategy == 'Minimise');
			ready = false;
			partScripts = data.scripts;
			userId = data.user;
			fixAnchors = fixLinks;
			tools = [
			{
				id: 'close',
				handler: function(e, target, panel) {
					portlet = panel.portlet;
					iCM.PersonalHomePage.Remove(portlet.uid);
				}
			}, {
				id: 'edit',
				handler: function(e, target, panel) {
					portlet = panel.portlet;
					panel.body.load(
						{ url: createUrl(portlet, true, articleId),
							scripts: partScripts
						}
					);
				}
}];

				// create dragpanel
				draggable = new Ext.Panel({
					autoHeight: true,
					id: target,
					applyTo: target,
					items: [{
						xtype: 'portal',
						margins: '5 5 5 5',
						listeners: {
							'drop': function(e) {
								portlet = e.panel.portlet;
								if (!portlet || portlet.v == 'C') {
									//This portlet has been dragged from the menu bar
									e.panel.load(createUrl(portlet, false, articleId));
									e.panel.addListener('expand', expand);
									e.panel.addListener('collapse', collapse);
									e.panel.expand();
									draggable.doLayout();
									if (iCM.PersonalHomePagePartBrowser) {
										iCM.PersonalHomePagePartBrowser.SwitchOnOff(portlet.aid, true);
									}
								}

								// Update portlet
								var oldColumn = portlet.c;
								var oldIndex = portlet.r;
								portlet.panel = e.panel;
								portlet.v = 'V';
								portlet.c = e.columnIndex;
								portlet.r = e.position;

								// Shift portlets in columns to account for changes
								updateUser(portlet);
								try {
									adjust(data, oldColumn, oldIndex, portlet, true);
								}
								catch (err) { }
							},
							'validatedrop': function(e) {
								if (hasMenu && e.columnIndex == columns.length - 1 && e.position == 0) {
									return false;
								} else {
									return true;
								}
							}
						}
}]
					});

					// Set up the columns
					var thePortal = draggable.items.items[0];
					if (data.columns) {
						for (colIdx = 0; colIdx < data.columns.length; colIdx++) {
							// Css classes
							var colCls = "column";
							var padding = "";
							if (data.stylecolumns) {
								padding += "padding-right: 10px;";
							}
							if (colIdx == 0) {
								colCls = "first-column";
							}
							else if (colIdx == data.columns.length - 1 && data.columns.length > 1) {
								colCls = "last-column";
								if (data.stylecolumns) {
									padding += "padding-right: 0px;";
								}
							}

							// Create the column container
							col = thePortal.add({
								cls: colCls,
								xtype: 'portalcolumn',
								style: padding,
								columnWidth: data.columns[colIdx]
							});

							// Store for later use
							columns.push(col);

							// If this is the last column, and one is required, add the menu pane
							if (hasMenu && colIdx == data.columns.length - 1) {
								col.add({
									title: 'Menu',
									id: 'portletMenu',
									xtype: 'portletMenu',
									defaultType: 'portletMenu',
									cls: 'x-portal-column'
								});
							}
						}
					}

					// Ask the state listener to restore the positions
					savedListener.RestoreState(articleId, data.items);

					// Set up the items in the columns
					for (portIdx = 0; portIdx < data.items.length; portIdx++) {
						var portlet = data.items[portIdx];
						registerPortlet(portlet);
						if (portlet.v == 'V' || (portlet.v == 'C' && hasMenu)) {
							var column = columns[portlet.c];
							if (column || (portlet.v == 'C' && hasMenu)) {
								addPortlet(column, portlet, true, true);
							}
						}
					}

					// Layout
					draggable.doLayout();

					window.onresize = function(e) { draggable.doLayout(); }

					// Part Browser
					if (iCM.PersonalHomePagePartBrowser) {
						iCM.PersonalHomePagePartBrowser.Build(state);
					}

					// Show display area
					Ext.get(target).dom.style.display = 'block';

					// Enable scrolling
					enableScrolling();

					ready = true;
				},

				// Change the title of a portlet
				ChangeTitle: function(objectid, newtitle) {
					var portlet = getPortletByObjectId(objectid);
					if (portlet) {
						var panel = portlet.panel;
						if (panel) {
							panel.setTitle(newtitle);
							portlet.ttl = newtitle;
							if (iCM.PersonalHomePagePartBrowser) {
								iCM.PersonalHomePagePartBrowser.Refresh();
							}
						}
					}
				},

				// Fix the links in a part's body text
				FixLinks: function(element, target, fixLinks) {
					if (element && (fixLinks == 'All')) {
						var links = element.getElementsByTagName('a');
						for (ilink = 0; ilink < links.length; ilink++) {
							var link = links[ilink];
							link.target = target;
							if (!link.title || (link.title && link.title.length == 0)) {
								link.title = link.innerHTML;
							}
							link.title += ' : This opens in a new window';
						}
						var forms = element.getElementsByTagName('form');
						for (iform = 0; iform < forms.length; iform++) {
							var form = forms[iform];
							if (form.getAttribute("class") != null && form.getAttribute("class").indexOf("pollform") >= 0) {
								form.target = "_blank";
							}
						}
					}
					else if (element && (fixLinks == 'ExternalOnly')) {
						var links = element.getElementsByTagName('a');
						for (var i = 0; i < links.length; i++) {
							var link = links[i];
							if (link.getAttribute("href") && link.getAttribute("rel") == "external") {
								link.target = target;
								if (!link.title || (link.title && link.title.length == 0)) {
									link.title = link.innerHTML;
								}
								link.title += ' : This opens in a new window';
							}
						}
					}
				},

				// 
				GetState: function() {
					return state;
				},

				// Delete a portlet. 
				Remove: function(id) {
					var portlet = getPortlet(id);
					if (portlet) {
						var panel = portlet.panel;
						if (panel) {
							// Remove portlet from display
							panel.ownerCt.remove(panel, true);

							// Remove to menu if required
							if (hasMenu) {
								addToMenu(portlet);
							}

							// Update portlet
							portlet.panel = null;
							portlet.v = 'C';
							updateUser(portlet);
						}

						if (portlet.reuse) {
							// Unregister
							unregisterPortlet(portlet);

							// Remove from state
							for (var key in state.items) {
								if (state.items[key].uid == portlet.uid) {
									delete state.items[key];
									break;
								}
							}
						}
						if (iCM.PersonalHomePagePartBrowser) {
							iCM.PersonalHomePagePartBrowser.Refresh();
						}
					}
				},

				// Toggle the visibility of a portlet in the personal home page
				Toggle: function(id) {
					var portlet = getPortlet(id);
					if (portlet) {
						var portletPanel = portlet.panel;
						if (portlet.v == 'V') {
							iCM.PersonalHomePage.Remove(id);
						} else {
							// Add portlet to display
							portlet.v = 'V';
							var column = columns[portlet.c];
							if (column) {
								addPortlet(column, portlet, true, false)
							}
							updateUser(portlet);

							// Remove from menu
							if (hasMenu) {
								var menuPanel = Ext.getCmp('m' + portlet.uid);
								if (menuPanel) {
									menuPanel.ownerCt.remove(menuPanel, true);
								}
							}
						}
						draggable.doLayout();
					}
				},

				// Initialise the personal home page. 'target' contains the Id of the target html element, 'data' contains a JSON
				// structure denoting the various portlets to be displayed and their status.
				Initialise: function(target, article, data, fixLinks, stateListener) {
					articleId = article;

					var params = Ext.urlDecode(location.search.substring(1));
					if (params['reset'] && params['reset'] == 'true') {
						stateListener.ResetState(article);
					}

					if (!data) {
						debug('State information not present. Fetching data from remote system...');
						iCM.RPC.PersonalHomePage.GetState(articleId,
					function(target, response) {
						debug('Loading state into html element "' + target + '"');
						iCM.PersonalHomePage.BuildDisplay(target, response.result, fixLinks, stateListener);
					},
					function(status) {
						alert('Could not fetch initial portal display. Status code: ' + status);
					},
					target
				);
					} else {
						iCM.PersonalHomePage.BuildDisplay(target, data, fixLinks, stateListener);
						draggable.doLayout();

						if (navigator.userAgent.indexOf("MSIE 6")) {
							var temp = Ext.get("ext-gen10").dom;

							if (temp && temp.getBoundingClientRect) {
								var rect = temp.getBoundingClientRect();
								var containerWidth = rect.right - rect.left;
								var calculatedWidth = (containerWidth / data.columns.length) - 10;

								var theColumns = Ext.query('.x-column');
								Ext.each(theColumns, function(aColumn) {
									aColumn.style["width"] = calculatedWidth + "px";
									aColumn.style["overflow"] = "hidden";
								});
							}
						}
					}
				}
			}
		} ();

PersonalHomePage.app = PersonalHomePage;
iCM.PersonalHomePage = PersonalHomePage;
