 
// 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 = {};

	// 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) {
		href = 'index.aspx?articleid=' + aportlet.aid;
		
		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: 'index.aspx?articleid=' + aportlet.aid + '&editmode=false&homepageid=' + 
								articleId + '&sequence=' + aportlet.seq + '&objectid=' + aportlet.oid,
					scripts: partScripts,
					callback: function(el, success, response, options) {
											iCM.PersonalHomePage.FixLinks(el.dom, '_blank');
										}
				}
			}
			
			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) {
		aportlet.v = 'C';
		var menu = Ext.getCmp('portletMenu');
		var panel = menu.add({
			title: aportlet.ttl,
			tools: aportlet.close ? tools : [],
			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 adjustParts(data, colIndex, portlet) {
		var partsInCol = [];
		for (var ipart=0; ipart<data.items.length; ipart++) {
			if (data.items[ipart].c == colIndex) {
				partsInCol.push(data.items[ipart]);
			}
		}
		partsInCol.sort(function (first, second) {
			if (first.r < second.r) {
				return -1;
			} else if (first.r > second.r) {
				return +1;
			} else if (first.r == second.r) {
				if (portlet) {
					return first == portlet ? -1 : +1;
				} else {
					return 0;
				}
			}
		});
		for (var ipart=0; ipart<partsInCol.length; ipart++) {
			partsInCol[ipart].r = ipart;
			updateUser(partsInCol[ipart]);
		}
	}

	// Panel has been collapsed
	function collapse(e) { 
		resize(e.portlet, true);
	};
	
	// Debug message
	function debug(msg) {
		try {
			if (!document.all && console) {
				console.log(msg);
			}
		} catch(err) {}
	}
    
	// 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 + ' (' + portlet.ttl + ') with object id #' + portlet.oid);
		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];
	};
	
	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.id + ', Object Id:' + portlet.oid + 
				', Part:' + portlet.aid + ', Sequence:' + portlet.seq + 
				', Minimized:' + portlet.ismin + ', Status:' + portlet.v + 
				', Column: ' + portlet.c + ', Row: ' + portlet.r);
		
			iCM.RPC.PersonalHomePage.UpdatePart(portlet.oid, articleId, portlet.aid, portlet.seq,
				portlet.ismin, portlet.v == 'C', portlet.c, portlet.r,  
				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
				portletClone.seq = 0;
				for (id in portletRegister) {
					if (portletRegister[id] && portletRegister[id].aid == portlet.aid)
						++portletClone.seq;
				}
				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: 'index.aspx?articleid=' + portletClone.aid + '&editmode=true&homepageid=' + 
											articleId + '&sequence=' + portletClone.seq + '&objectid=' + portletClone.oid,
								scripts: partScripts,
								callback: function(el, success, response, options) {
									iCM.PersonalHomePage.FixLinks(el.dom, '_blank');
								}
							});
						}
					);
					draggable.doLayout();
					if (iCM.PersonalHomePagePartBrowser) {
						iCM.PersonalHomePagePartBrowser.Refresh();
					}
				}
			}
		},
		
		// Build the display
		BuildDisplay: function(target, data) {
			state = data;
			hasMenu = (data.closestrategy == 'Minimise');
			ready = false;
			userId = data.user;
			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: 'index.aspx?articleid=' + portlet.aid + '&editmode=true&homepageid=' + 
								articleId + '&sequence=' + portlet.seq + '&objectid=' + portlet.oid,
							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.displayed) {
								//This portlet has been dragged from the menu bar
								e.panel.load('index.aspx?articleid=' + portlet.aid);
								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;
							portlet.panel = e.panel;
							portlet.v = 'V';
							portlet.c = e.columnIndex;
							portlet.r = e.position;
							updateUser(portlet);

							// Shift portlets in columns to account for changes
							if (e.columnIndex != oldColumn) {
								adjustParts(data, oldColumn, null);
							} 
							adjustParts(data, e.columnIndex, portlet); 
						},
						'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'
						});
					}
				}
			}
			
			// 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);
			}
			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) {
			if (element) {
				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'; 
				}	
			}
		},
		
		// 
		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) {
			articleId = 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);
					},
					function(status) {
						alert('Could not fetch initial portal display. Status code: ' + status);
					},
					target
				);
			} else {
				iCM.PersonalHomePage.BuildDisplay(target, data);
			}
		}
	}
}();

PersonalHomePage.app = PersonalHomePage;
iCM.PersonalHomePage = PersonalHomePage;