IAL_GhostPortalWindow = Class.create();
IAL_GhostPortalWindow.prototype = Object.extend(new IAL_PortalWindowBase(), {
	_initWindow: function()
	{
		if (this.initialized) return;

		var div = document.createElement('div');
		div.className = 'ghostPortletWindow';
		div.style.display = 'none';
		div.style.position = 'absolute';
		div.id = this.getId();
		
		var parent = document.getElementById('tabTest');
		parent = parent || document.body;
		this.setOption('parent', parent);
		parent.appendChild(div);

		this.initialized = true;
	}
});

var IAL_PortalWindowManagerHelper =
{
	falseFunction: function()
	{
		return false;
	},
	
	getCurrentManager: function()
	{
		return IAL_PortalWindowManager.prototype.$();
	},
		
	getActiveDraggable: function()
	{
		var manager = this.getCurrentManager();
		var draggable = null;
		if (manager)
		{
			draggable = manager.getActiveDraggable();
		}
		
		return draggable;
	}
};

function IAL_PortalSizeManager(winManager)
{
	this.winManager = winManager;
	this.ghostWindow = new IAL_GhostPortalWindow('IAL_PortalWindowManager_ghostWindow');
	this._windows = $H();
}

IAL_PortalSizeManager.prototype =
{
	_windows: $H(),

	constructor: IAL_PortalSizeManager,
	
	addWindow: function(win)
	{
		this._windows[win.getId()] = win.getSize();
	},
	
	removeWindow: function(winId)
	{
		this._windows.remove(winId);
	},
	
	getSize: function(winId)
	{
		return this._windows[winId] ? this._windows[winId] : null;
	},
	
	getSize2: function(winId, options)
	{
		var size = this.getSize(winId);
		size = Object.clone(size);
		var win = this.winManager.getWindow(winId);
		if (win) 
		{
			if (!options.savedPosition)
			{
				var position = win.getPosition();
				size = Object.extend(size, position);
			}
			
			if (!options.savedSize)
			{
				var newSize = win.getSize2();
				size = Object.extend(size, newSize);
			}
			
			this._windows[winId] = Object.clone(size);
		}
		
		return size;
	},
	
	setSize: function(winId, size, setSize)
	{
		var win = this.winManager.getWindow(winId);
		if (win) 
		{
			setSize = size;//setSize || size;
		
			win.setSize(setSize);
			this._windows[winId] = size;
		}
	},
	
	applyChanges: function(newSizes, options)
	{
		var sizeManager = this;
		var containerWidth = 0;
		var containerHeight = 0;
		
		newSizes.each(function(item)
		{
			if (!item || !(sizeManager._windows[item.winId])) throw $continue;

			var oldSize = sizeManager._windows[item.winId];
			var newSize = item.size;
			
			var curContainerWidth = newSize.width + newSize.left;
			if (curContainerWidth > containerWidth) containerWidth = curContainerWidth;
			
			var curContainerHeight = newSize.height + newSize.top;
			if (curContainerHeight > containerHeight) containerHeight = curContainerHeight;
			
			if (options.useShadowWindow && options.activeWindowId == item.winId)
			{
				sizeManager.ghostWindow.setSize(newSize);
			}
			else if (oldSize.top != newSize.top ||
				oldSize.left != newSize.left ||
				oldSize.height != newSize.height ||
				oldSize.width != newSize.width)
			{
				if (newSize.left < 0) newSize.left = 0;

				var setSize = {};
				if (oldSize.top != newSize.top) setSize.top = newSize.top;
				if (oldSize.left != newSize.left) setSize.left = newSize.left;
				if (oldSize.width != newSize.width) setSize.width = newSize.width;
				if (oldSize.height != newSize.height) setSize.height = newSize.height;

				sizeManager.setSize(item.winId, newSize/*, setSize*/);
			}
		});
		
		var cnt = $('tabTest');
		if (cnt)
		{
			cnt.style.width = containerWidth ? containerWidth + 'px' : '100%';
			cnt.style.height = containerHeight && containerHeight > 400 ? containerHeight + 'px' : '100%';
		}
	},
	
	doGravity: function()
	{
		var options = Object.extend({
			activeWindowId: null,
			useShadowWindow: false,
			savedPosition: false,
			savedSize: false
			}, arguments[0] || {})

		var ghostWindow = this.ghostWindow;
		if (options.activeWindowId && options.useShadowWindow)
		{
			var activeWin = this.winManager.getWindow(options.activeWindowId);
		
			ghostWindow.setOption('parent', activeWin.getOption('parent'));
			ghostWindow.show();
		}
		else
		{
			ghostWindow.hide();
		}
	
		var sortedWindows = this.getSortedWindows(options, this.lastActiveWindowId);
		sortedWindows = this.normalizeWindows(sortedWindows);

		this.applyChanges(sortedWindows, options);
		
		this.lastActiveWindowId = options.activeWindowId;
	},
	
	getSortedWindows: function(options, reloadWinId)
	{
		var sortedWindows = [];
		var sizeManager = this;

		this._windows.each(function(pair)
		{
			var winId = pair.key;
			var isFromCache = (winId != options.activeWindowId && winId != reloadWinId);
			var winSize = isFromCache ? Object.clone(pair.value) : sizeManager.getSize2(winId, options);
			if (!isFromCache && winSize.left < 0 && options.useShadowWindow && options.activeWindowId)
			{
				winSize.left = 0;
			}

			sortedWindows.push({winId: pair.key, size: winSize, fixed: false, sizeChanged: false});
		});

		for (var i = sortedWindows.length - 1; i > 0; i--)
		{
			var sorted = true;
			for (var j = 0; j < i; j++)
			{
				var jTop = sortedWindows[j].size.top;
				var j1Top = sortedWindows[j + 1].size.top;
				var id = sortedWindows[j + 1].winId;
				if ((jTop > j1Top) ||
					(jTop == j1Top &&
					(id == 'IAL_PortalWindowManager_ghostWindow' ||
					id == options.activeWindowId)))
				{
					var tempWin = sortedWindows[j + 1];
					sortedWindows[j + 1] = sortedWindows[j];
					sortedWindows[j] = tempWin;
					sorted = false;
				}
			}
			
			if (sorted) break;
		}

		return sortedWindows;
	},
	
	normalizeWindows: function(sortedWindows)
	{
		for (var i = 0; i < sortedWindows.length; i++)
		{
			var currentWindow = sortedWindows[i];
			var prevTop = currentWindow.size.top;
			currentWindow.size.top = 0;
			
			var curSize = currentWindow.size;
			if (curSize.left < 0)
			{
				curSize = Object.clone(curSize);
				curSize.left = 0;
			}
			for (var j = 0; j < i; j++)
			{
				var tempWindow = sortedWindows[j];
				var tempSize = tempWindow.size;
				if (tempSize.left < 0)
				{
					tempSize = Object.clone(tempSize);
					tempSize.left = 0;
				}

				if (this.isWindowsIntersectX(curSize, tempSize) &&
					curSize.top < tempSize.top + tempSize.height + 1)
				{
					curSize.top = tempSize.top + tempSize.height + 1;
				}
			}

			if (curSize.top != prevTop)
			{
				currentWindow.size.top = curSize.top;
				sorted = false;
			}
			sortedWindows[i] = currentWindow;
		}
		
		return sortedWindows;
	},
	
	isWindowsIntersect: function(winSize1, winSize2)
	{
		return this.isWindowsIntersectX(winSize1, winSize2) &&
			this.isWindowsIntersectY(winSize1, winSize2);
	},
	
	isWindowsIntersectX: function(winSize1, winSize2)
	{	
		return ((winSize1.left <= winSize2.left && winSize2.left <= winSize1.left + winSize1.width) ||
			(winSize1.left <= winSize2.left + winSize2.width && winSize2.left <= winSize1.left + winSize1.width));
	},
	
	isWindowsIntersectY: function(winSize1, winSize2)
	{
		return ((winSize1.top <= winSize2.top && winSize2.top <= winSize1.top + winSize1.height) || 
			(winSize1.top <= winSize2.top + winSize2.height && winSize2.top <= winSize1.top + winSize1.height));
	}
};

var IAL_PortalWindowManager = createDerivedClass(IAL_BasePortalControl,
	{
		constructor: function()
		{
			// call base constructor
			this.constructor();
			
			this.isGravity = true;
			this.windows = $H();
			this.isLoaded = false;
			this._removeWindowHandlers = [];
			this.winSizeManager = new IAL_PortalSizeManager(this);
		},

		$: function()
		{
			return IAL_PortalWindowManager.prototype._currentPortalWindowManager;
		},
		
		setCurrentPortalWindowManager: function(currentPortalWindowManager)
		{
			if( (currentPortalWindowManager == null) && (typeof(currentPortalWindowManager) != "undefined"))
			{
				IAL_PortalWindowManager.prototype._currentPortalWindowManager = currentPortalWindowManager;
			}
			else
			{
				IAL_PortalWindowManager.prototype._currentPortalWindowManager = currentPortalWindowManager || this;
			}
		},
		
		startDrag: function(draggable)
		{
			this._activeDraggable = draggable;
			draggable.loadOldState = false;
			this._saveState();
		},
		
		endDrag: function(draggable)
		{
			if (draggable.loadOldState) this._loadState();
			this._savedStates = null;
			this._activeDraggable = null;			
		},
		
		changeDrag: function(draggable)
		{
		},
		
		getActiveDraggable: function()
		{
			return this._activeDraggable;
		},
		
		removeFromSaveState: function(id)
		{
			if (this._savedStates && this._savedStates[id])
			{
				this._savedStates.remove(id);
			}
		},
		
		_saveState: function()
		{
			var states = $H();
			this.windows.each(function(pair)
			{
				states[pair.key] = pair.value.getSize();
			});
			
			this._savedStates = states;
		},
		
		_loadState: function()
		{
			if (!this._savedStates) return ;

			var windows = this.windows;
			var winManager = this;
			this._savedStates.each(function(pair)
			{
				var win = windows[pair.key];
				if (win) 
				{
					winManager.setSize(pair.key, pair.value);
					//win.setSize(pair.value);
				}
			});
				
			this._savedStates = null;
		},
		
		setSize: function(winId, size)
		{
			this.winSizeManager.setSize(winId, size);
		},
		
		addWindow: function(win)
		{
			this.windows[win.getId()] = win;
			this.winSizeManager.addWindow(win);
		},

		clearChildControls: function()
		{
			this.destroy();
		},

		createSandbox: function(options)
		{
			if (this.sandBox) 
			{
				this.sandBox.show();
				return this.sandBox;
			}
			
			options = options || {};
			options['eventHandlers'] = this.getDefaultPortletHandlers(
			{
				'onRemoveSubscription': function()
				{
					var manager = IAL_PortalWindowManagerHelper.getCurrentManager();
					manager.doGravity2({activeWindowId: this.getId(), savedPosition: true});
				},
				
				'onAddSubscription': function()
				{
					var manager = IAL_PortalWindowManagerHelper.getCurrentManager();
					manager.doGravity2({activeWindowId: this.getId(), savedPosition: true});
				},
				
				'onClose': function()
				{
					var manager = IAL_PortalWindowManager.prototype.$();

					manager.removeWindow(this.getId(), true);
					manager.removeSandBox();
					manager.doGravity2();
					PortalTabsHelper.saveCurrentState();
				},
				'onDropSubscription': function()
				{
					var draggable = IAL_PortalWindowManagerHelper.getActiveDraggable();
					if (draggable) draggable.loadOldState = true;
				},
				'onDropSubscriptionSuccessfully': function()
				{
					IAL_PortalWindowManager.prototype.$().removeFromSaveState(this.getId());
				},
				'onDragStart': null,
				'onDragEnd': null
			});

			this.sandBox = new IAL_SandboxWindow('winSandbox', options);
			this.sandBox.show();
			
			this.addWindow(this.sandBox);
			
			return this.sandBox;
		},
		
		getSandBox: function()
		{
			return this.sandBox;
		},
		
		hasSandbox: function()
		{
			return !!(this.sandBox);
		},

		removeSandBox: function()
		{
			if (this.sandBox) 
			{
				this.sandBox.hide();
				this.sandBox.destroy();
			}
			this.sandBox = null;
		},

		createWindow: function(id, type, options)
		{
			var win;
			options = options || {};
			options['eventHandlers'] = this.getDefaultPortletHandlers();
			
			eval('win = new ' + type + '(id, options)');
			win.show();

			this.addWindow(win);
			
			return win;
		},
		
		getDefaultPortletHandlers: function(overrideHandlers)
		{
			return Object.extend({
				'onDrag': function()
				{
					IAL_PortalWindowManager.prototype.$().doGravity2({activeWindowId: this.getId(), useShadowWindow: true, savedSize: true});
				},
				'onDragStart': function(eventName, draggable)
				{
					var parent = this.getOption('parent');
					YAHOO.util.Dom.removeClass(parent, 'inactiveDrag');
					YAHOO.util.Dom.addClass(parent, 'activeDrag');
					
					var sandBox = IAL_PortalWindowManager.prototype.$().getSandBox();
					if (sandBox) sandBox.showMessage('You can drop element here');
				},
				'onDragEnd': function(eventName, draggable)
				{
					var parent = this.getOption('parent');
					YAHOO.util.Dom.removeClass(parent, 'activeDrag');
					YAHOO.util.Dom.addClass(parent, 'inactiveDrag');
					
					var sandBox = IAL_PortalWindowManager.prototype.$().getSandBox();
					if (sandBox) sandBox.hideMessage();
				},
				'onDragRevert': function()
				{
					IAL_PortalWindowManager.prototype.$().doGravity2({savedSize: true}); 
					IAL_PortalWindowManager.prototype.$().showWindowsContent(); 
					PortalTabsHelper.saveCurrentState(); 
				},
				'onResize': function()
				{
					IAL_PortalWindowManager.prototype.$().doGravity2({activeWindowId: this.getId(), useShadowWindow: true, savedPosition: true});
				},
				'onResizeEnd': function()
				{
					var x_man = IAL_PortalWindowManager.prototype.$();
					x_man.doGravity2();
					PortalTabsHelper.saveCurrentState();
					//redraw window
					x_man.showWindowsContent();
				},
				'onMinimize': function()
				{
					IAL_PortalWindowManager.prototype.$().doGravity2({activeWindowId: this.getId(), savedPosition: true});
					PortalTabsHelper.saveCurrentState();
				},
				'onMaximize': function()
				{
					IAL_PortalWindowManager.prototype.$().doGravity2({activeWindowId: this.getId(), savedPosition: true});
					PortalTabsHelper.saveCurrentState();
				},
				'onHideProperties': function()
				{
					IAL_PortalWindowManager.prototype.$().doGravity2({activeWindowId: this.getId(), savedPosition: true});
				},
				'onShowProperties': function()
				{
					IAL_PortalWindowManager.prototype.$().doGravity2({activeWindowId: this.getId(), savedPosition: true});
				},
				'onClose': function()
				{
					var currentWindowsManager = IAL_PortalWindowManager.prototype.$();
					var title = this.getTitle();
					var confirmed = true;
					var selTab = tabs.getSelectedTab();
					var prop = PortalTabsHelper.getTabProperties(selTab);
					if (prop.state == 2)
					{
						confirmed = confirm('This action will remove this portlet from this community tab of every Library user');
					}

					if(confirmed)
					{
						currentWindowsManager.removeWindow(this._id, true);
						currentWindowsManager.doGravity2();
						if (this.type == 'IAL_PortalWindowStaticContent')
						{
							PortalTabsHelper.removeStaticContentFromTab(this._id);
						}
						else
						{
							PortalTabsHelper.removeSubscriptionFromTab(this._id, title);
						}
						PortalTabsHelper.saveCurrentState();
						return false;
					}
				}
			}, overrideHandlers || {});
		},
		
		storeSize: function()
		{
			var savedSize = $H();
			this.windows.each(function(pair)
			{
				savedSize[pair.key] = pair.value.getSize();
			});
			
			this._savedSize = savedSize;
		},
		
		restoreSize: function()
		{
			if (this._savedSize)
			{
				var savedSize = this._savedSize;
				var winManager = this;
				this.windows.each(function(pair)
				{
					if (savedSize[pair.key]) 
					{
						winManager.setSize(pair.key, savedSize[pair.key]);
					}
				});
			}
		
			this._savedSize = null;
		},
		
		doGravity2: function(options)
		{
			options = Object.extend({}, (options || {}));

			this.winSizeManager.doGravity(options);
		},
		
		showWindowsContent: function()
		{
			var parent = this.getParent();
			if (parent) YAHOO.util.Dom.removeClass(parent, 'enabledHelpDiv');
		},
		
		hideWindowsContent: function()
		{
			var parent = this.getParent();
			if (parent) YAHOO.util.Dom.addClass(parent, 'enabledHelpDiv');
		},
		
		getParent: function()
		{
			if (this.parent) return this.parent;
			this.parent = null;
			if (this.windows)
			{
				this.parent = this.windows.values()[0].getOption('parent');
				if (this.parent == null) this.parent = document.body;
			}

			return this.parent;
		},
		
		revertGravity: function()
		{
			this.isGravity = !this.isGravity;
			if (this.isGravity)
			{
				this.doGravity2();
			}
		},
		
		getWindow: function(id)
		{
			return id != 'IAL_PortalWindowManager_ghostWindow' ? this.windows[id] : this.ghostWindow;
		},
		
		addRemoveWindowHandler: function(handler)
		{
			if (handler) this._removeWindowHandlers.push(handler);
		},
		
		removeWindow: function(winId, fullRemove)
		{
			if (fullRemove)
			{
				var win = this.getWindow(winId);
				if (win) win.hide();
			}
			this.windows.remove(winId);
			
			if (fullRemove && this._removeWindowHandlers)
			{
				for (var i = 0; i < this._removeWindowHandlers.length; i++)
				{
					var handler = this._removeWindowHandlers[i];
					handler(this, winId);
				}
			}
			
			this.winSizeManager.removeWindow(winId);
		},
		
		activate: function()
		{
			this.windows.each(function (pair)
			{
				pair.value.show();
			});

			this.doGravity2();
		},
		
		deactivate: function()
		{
			this.windows.each(function(pair)
			{
				if (pair.value.isVisible()) pair.value.hide();
			});
		},
		
		getState: function(xmlNode)
		{
			if (this.windows.keys().size() > 0)
			{
				this.getChildState(xmlNode);
			}
		},
		
		getChildState: function(xmlNode)
		{
			this.windows.each(function(pair)
			{
				if (pair.value.getOption('statusable')) pair.value.getState(xmlNode);
			});
		},

		getChildShared: function(sharedState)
		{
			var sharedNames = [];
			this.windows.each(function(pair)
			{
				if (sharedState == pair.value.getPortletSharedState())
					sharedNames.push(pair.value.getTitle());
			});

			return sharedNames;
		}, 

		isManagerConatainThisWindow: function(windowTitle)
		{
			var isTitleExist = false;
			this.windows.each(function(pair)
			{
				if (pair.value.getTitle() == windowTitle)
				{
					isTitleExist = true;	
					throw $break;
				}
			});

			return isTitleExist;		
		}, 

		loadState: function(containerId, stateXml, isFixed, overrideProperties)
		{
			var windowNodeList = stateXml.documentElement.selectNodes('window');
			for (var i = 0; i < windowNodeList.length; i++)
			{
				var windowNode = windowNodeList[i];
				var type = windowNode.getAttribute('type');

				//var contentNode = windowNode.selectSingleNode('Module/Content');                
                var isMinimized = ("true" == windowNode.getAttribute("minimize"));
                var winProperties = {parent: containerId,
					title: windowNode.getAttribute('title'),
					top: windowNode.getAttribute('top'),
					left: windowNode.getAttribute('left'),
					width: windowNode.getAttribute('width'),
					height: windowNode.getAttribute('height'),
					state: windowNode.getAttribute('state'),
					url: windowNode.getAttribute('url'),
					shared: windowNode.getAttribute('shared') == "true" ? true : false, 
					moduleXml: windowNode.selectSingleNode('Module'),
					portletTypeInt: windowNode.getAttribute('portletTypeInt') != null ? windowNode.getAttribute('portletTypeInt') : "2",
                    resizable: !isFixed,
		            closable: !isFixed,
		            draggable: !isFixed,
		            hasProperties: !isFixed,
		            minimizable: !isFixed,
		            maximizable: isMinimized && !isFixed,
		            isMinimize: isMinimized};
				if (overrideProperties)
				{
					winProperties = Object.extend(winProperties, overrideProperties);
				}

				var win = this.createWindow(windowNode.getAttribute('id'), type, winProperties);
			}

			this.doGravity2();
			this.isLoaded = true;
		},
		
		destroy: function()
		{
			this.windows.each(function(pair)
			{
				pair.value.destroy();
			});
			
			this.windows = $H();
		},
		
		sandBox: null,
		
		isGravity: true,
		
		windows: [],
		
		_currentPortalWindowManager: null,
		
		isLoaded: false,
		
		ghostWindow: new IAL_GhostPortalWindow('IAL_PortalWindowManager_ghostWindow')
	});
