/**
 * myWindowFactory
 * 
 * a class for openenig popup windows, ether as real windows or as inline popups
 * 
 * Version 1.1
 * 
 * Copyright (c) 2006, 2007 Stefan Schindler (stefan.schindler@gmx.at)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

var myWindowFactory = Class.create();
myWindowFactory.prototype = {
	
	instance : null,
	windows: new Array(),
	inlineWindowTemplate:null,
	lockTemplate:null,
	isIE: null,
	isIE6: null,
	isIE7: null,
	isOpera: null,
	customized: false,
	checkClosed: null,
	baseUrl: null,
	zIndexStep: 20,
	settings: {
		
		zIndex: 100,
		minWidth: 100,
		minHeight: 100,
		inlineMode: true,
		showName: false,
		containerIdPart: 'container',
		contentIdPart: 'content',
		lockId: 'wfLock',
		contentLockIdPart: 'contentLock',
		topIdPart: 'top',
		dragHandleIdPart: 'dragHandle',
		middleIdPart: 'middle',
		bottomIdPart: 'bottom',
		resizeHandleIdPart: 'resizeHandle',
		width: 400,
		height: 400,
		draggable: true,
		resizeable: true,
		resizeX: true,
		resizeY: true,
		lockBgImg:null,
		contentLockBgImg:null,
		callback: null,
		closeText: 'close',
		closeAltTitle: 'close',
		closeFunction: null,
		offsetX: 15,
		offsetY: 15,
		positionOffset: false,
		lockBackground: true,
		
		//styleSheet: null,
		//loadStyleSheet: null,
			
		containerClass: 'wfContainer',
		containerClassIE6: 'wfContainerIE6',
		closeClass: 'wfClose',
		closeClassIE6: 'wfCloseIE6',
		contentClass: 'wfContent',
		lockClass: 'wfLock',
		contentLockClass: 'wfContentLock',
		topClass: 'wfTop',
		dragHandleClass: 'wfDragHandle',
		middleClass: 'wfMiddle',
		bottomClass: 'wfBottom',
		resizeHandleClass: 'wfResizeHandle'	
	},
			
	initialize: function()
	{
		var head = document.getElementsByTagName('head')[0];

		if (head)
		{
			var scripts = head.getElementsByTagName('script');
			for (var i=0; i<scripts.length; i++)
			{
				var s = scripts[i].src;
				if(s && (s.indexOf("windowFactory.js") != -1))
				{
					if(!/\//.test(s))
					{
						var wl = window.location;
						this.baseUrl = wl.protocol + '//' + wl.hostname + wl.pathname.substring(0, wl.pathname.lastIndexOf('/'));
					}
					else
					{
						this.baseUrl = s.substring(0, s.lastIndexOf('/'));
					}
					break;
				}
			}
		}
		
		if(/MSIE/.test(navigator.userAgent) && !window.opera)
		{
			this.isIE = true;
			
			if(/MSIE 6/.test(navigator.userAgent))
			{
				this.isIE6 = true;
				
			}
			if(/MSIE 7/.test(navigator.userAgent))
			{
				this.isIE7 = true;
			}
		}
		if(window.opera)
		{
			this.isOpera = true;
		}
		
		this.instance = this;
		
		this._focusPopup = this.focusPopup.bindAsEventListener(this);
		this._onScroll = this.onScroll.bindAsEventListener(this);
		this.commitCallback = this.__commitCallback.bind(this);
		
		this._closePopup = this.closePopup.bind(this);
		
		this.settings.closeFunction = this._closePopup;
		this.settings.callback = this.myAlert.bind(this);
	},
	
	myAlert: function(args)
	{
		alert(args);
		//WindowFactory.closePopup();
	},
	
	setSettings: function(settings)
	{
		var i=0;
		for(var prop in settings)
		{
			this.settings[prop] = settings[prop];
			i++;
		}
		if(i)
		{
			this.customized = true;
		}
		
		if(!this.settings.inlineMode)
		{
			this._checkPopupClosed = this.checkPopupClosed.bind(this);
		}
	},
	
	getInstance: function(settings)
	{
		if(settings && typeof(settings) == 'object' && !this.customized)
		{
			this.setSettings(settings);
		}
		return this.instance;
	},
	
	incZIndex: function()
	{
		this.settings.zIndex += this.zIndexStep;
		return this.settings.zIndex;
	},
	
	decZIndex: function()
	{
		this.settings.zIndex -= this.zIndexStep;
	},
	
	setZIndex: function(z)
	{
		this.settings.zIndex = Math.abs(parseInt(z));
	},
	
	setInlineMode: function()
	{
		this.settings.inlineMode = true;
	},
	
	setInlineWindowTemplate: function(elem)
	{
		elem = $(elem);
		elem.cleanWhitespace();
		this.inlineWindowTemplate = elem.innerHTML;
		elem.remove();
	},
	
	setLockTemplate: function(elem)
	{
		elem = $(elem);
		elem.cleanWhitespace();
		this.lockTemplate = elem.innerHTML;
		elem.remove();
	},
	
	//inline && name => options
	openPopup: function(target, name, options)
	{
		this.windows.push(new myWindow(target, name, options));
		
		var win = this.windows[this.windows.length-1];
		
		if(this.isIE6 && win.inline)
		//if(true)
		{
			this.disableAllSelects(win);
		}
		
		if(win.lockBackground)
		{
			this.lockBackground();
		}
	},
	
	closePopup: function(winName)
	{
		var w, win;
		var maxIndex = this.windows.length-1;
		for(var i = 0; i <= maxIndex; i++)
		{
			w = this.windows[i];
			if(w.windowName == winName)
			{
				if(i < maxIndex)
				{
					for(var j = maxIndex; j > i; j--)
					{
						this.destroyPopup(this.windows[j]);						
					}
				}
				this.destroyPopup(w);	
				break;
			}
		}		
	},
	
	destroyPopup: function(win)
	{
		win.closePopup();
		
		if(this.isIE6 && win.inline)
		//if(true)
		{
			this.enableAllSelects(win);
		}
		
		if(win.lockBackground)
		{
			this.unlockBackground(win);
		}
		this.windows.pop();
	},
	
	focusPopup: function(e)
	{
		var l = this.windows.length;
		if(l)
		{
			this.windows[l-1].win.focus();
		}		
	},
	
	checkPopupClosed: function()
	{
		for(var i = this.windows.length-1; i>=0; i--)
		{
			if(this.windows[i].windowClosed())
			{
				this.closePopup();
			}
		}
	},
	
	lockBackground: function()
	{
		var win = this.windows[this.windows.length-1];
		var zIndex = win.zIndex - this.zIndexStep/2;
		var pw = win.parentWindow;
		var pd = win.parentDocument;
		
		this.lockWindow(pw, pd, zIndex);
		
		//if popup is not inline and lock was initialy created or hidden
		if(this.windows.length && !this.windows[this.windows.length-1].inline && lock.getStyle('display') == 'none')
		{
			Event.observe(lock, "click", this._focusPopup);
			Event.observe(document, "focus", this._focusPopup);
			this.checkClosed = window.setInterval(this._checkPopupClosed, 250);
		}
		
		this.blockScrolling(win);
	},
	
	lockWindow: function(parentWindow, parentDocument, zIndex)
	{
		var lock = this.getOrCreateLock(parentWindow, parentDocument);
		
		if(!zIndex)
		{
			zIndex = this.incZIndex();
		}
		
		lock.style.zIndex = zIndex;
		
		lock.show();
	},
	
	getOrCreateLock: function(parentWindow, parentDocument)
	{
		if(!parentWindow)
		{
			parentWindow = window;
			parentDocument = window.document;
		}
		
		var lockId = this.settings.lockId;
		var lock = parentWindow.$(lockId);
		
		if(!lock)
		{
			var lockBg;
			
			var html = parentWindow.$(parentDocument.getElementsByTagName("html")[0]);
			var body = parentWindow.$(parentDocument.getElementsByTagName("body")[0]);
			
			var height = '100%';
			
			if(html.scrollHeight > html.offsetHeight)
			{
				height = html.scrollHeight + 'px';
			}
			else
			{
				height = html.offsetHeight + 'px';
			} 
			
			var width = "100%";
			
			
			if(this.lockTemplate)
			{
				lock = this.lockTemplate;
			}
			else
			{
				if(this.settings.lockBgImg)
				{
					lockBg = 'background: url('+this.baseUrl+'/'+this.settings.lockBgImg+') repeat;';
				}
				else
				{
					lockBg = 'background-color: silver;opacity:0.5;filter: alpha(opacity=50);';
				}
				
				lock = "<div id='"+ lockId +"' class='"+this.settings.contentLockClass+"' style='display:none;height:"+height+";width:"+width+"; "+lockBg+" position:absolute;top:0;left:0;'>"+
						"</div>";
						
				/*
				lock = "<iframe frameborder='0'; src=''; id='"+ lockId +"' class='"+this.settings.contentLockClass+"' style='display:none;height:"+height+";width:"+width+";background-color:none;"+lockBg+" position:absolute;z-index:"+this.incZIndex()+";top:0;left:0;'>"+
						"</div>";
				*/
			}
			new parentWindow.Insertion.Top(body,lock);
			
			lock = parentWindow.$(lockId);
		}
		
		return lock;
	},
	
	unlockBackground: function(win)
	{
		var maxIndex = this.windows.length - 1;
		var w = this.windows[maxIndex];
		
		var parentWindow = w.parentWindow;
		var parentDocument = w.parentDocument;
		var lock = parentWindow.$(this.settings.lockId);
		
		if(lock)
		{
			if( maxIndex == 0 || !this.windows[maxIndex-1].lockBackground )
			{
				this.unlockWindow(parentWindow);
				
				if(!w.inline)
				{
					Event.stopObserving(lock, "click", this._focusPopup);
					Event.stopObserving(parentDocument, "focus", this._focusPopup);
					window.clearInterval(parentWindow.checkClosed);
				}
				
				this.unblockScrollling(win);
			}
			else
			{
				var z;
				
				for(var i = maxIndex; i >= 0; i--)
				{
					if(this.windows[maxIndex].parentWindow != window)
					{
						this.unlockWindow(parentWindow);
						break;
					}
					else 
					{
						if(i > 0)
						{
							if(this.windows[i-1].lockBackground && this.windows[i-1].parentWindow == window)
							{
								z = this.windows[i-1].zIndex;
								lock.style.zIndex = z - this.zIndexStep/2;
								break;
							}
						}
						else
						{
							this.unlockWindow(parentWindow);
						}
					}
				}
			}
		}		
	},
	
	unlockWindow: function(parentWindow)
	{
		if(!parentWindow)
		{
			parentWindow = window;
		}
		var lock = parentWindow.$(this.settings.lockId);
		lock.hide();
		this.decZIndex();
	},
	
	disableAllSelects: function(win)
	{
		var maxIndex = this.windows.length - 1;
		if(maxIndex > 0)
		{
			var w = this.windows[maxIndex-1];
			if(!w.selectsDisabled)
			{
				w.selectsDisabled = true;
				this.disableSelects(w.contentWindow.document);
			}
		}
		else
		{
			this.disableSelects(win.parentDocument);
		}
		
		/*
		for(var i = maxIndex; i >= 0; i--)
		{
			if(i > 0)
			{
				var w = this.windows[i-1];
				if(!w.selectsDisabled)
				{
					w.selectsDisabled = true;
					this.disableSelects(w.contentWindow.document);
				}
			}
			else
			{
				this.disableSelects(win.parentDocument);
			}
		}
		*/
	},
	
	disableSelects: function(doc)
	{
		var elems = doc.getElementsByTagName('select');
		for(var i = 0;i < elems.length; i++)
		{
			elems[i].style.visibility = "hidden";
		}
	},
	
	enableAllSelects: function(win)
	{
		var maxIndex = this.windows.length - 1;
		if(maxIndex > 0)
		{
			var w = this.windows[maxIndex-1];
			if(w.selectsDisabled)
			{
				w.selectsDisabled = false;
				this.enableSelects(w.contentWindow.document);
			}
		}
		else
		{
			this.enableSelects(win.parentDocument);
		}
		/*
		debugger;
		var w = this.windows[this.windows.length -1];
		if(w.selectsDisabled)
		{
			w.selectsDisabled = false;
			this.enableSelects(w.parentDocument);
		}
		*/
	},
	
	enableSelects: function(doc)
	{
		var elems = doc.getElementsByTagName('select');
		for(var i = 0;i < elems.length; i++)
		{
			elems[i].style.visibility = "visible";
		}
	},
	
	blockScrolling: function(win)
	{
		var pw = win.parentWindow;
		var pd = win.parentDocument;
		
		
		if(this.isIE)
		{
			var html = pw.$(pd.getElementsByTagName("html")[0]);
			html.style.overflow = 'hidden';
		}
		else if(this.isOpera)
		{
			var html = pw.$(pd.getElementsByTagName("html")[0]);
			html.style.overflow = 'hidden';
		}
		else
		{
			Event.observe(pw, 'DOMMouseScroll', this._onScroll);
		}
	},
	
	unblockScrollling: function(win)
	{
		var pw = win.parentWindow;
		var pd = win.parentDocument;
		
		if(this.isIE)
		{
			var html = pw.$(pd.getElementsByTagName("html")[0]);
			html.style.overflow = 'auto';
		}
		else if(this.isOpera)
		{
			var html = pw.$(pd.getElementsByTagName("html")[0]);
			html.style.overflow = 'auto';
		}
		else
		{
			Event.stopObserving(pw, 'DOMMouseScroll', this._onScroll);
		}
	},
	
	__commitCallback: function(args)
	{
		var i = this.windows.length-1;
		this.windows[i].commitCallback(args);
	},

	calcPosition: function(win, width, height)
	{
		//console.info('width: ' + width + ', height: ' + height);
		
		var vpWidth,vpHeight,html;
		if(win.inline)
		{
			if(this.isIE)
			{
				vpWidth = win.parentDocument.body.clientWidth;
				vpHeight = win.parentDocument.documentElement.clientHeight;
			}
			else
			{
				vpWidth = win.parentWindow.innerWidth;
				vpHeight = win.parentWindow.innerHeight;
			}
		}
		else
		{
			vpWidth = screen.width;
			vpHeight = screen.height;
		}
		
		var x = parseInt((vpWidth / 2) - (width / 2));
		var y = parseInt((vpHeight / 2) - (height / 2));
		
		// (inline | popup) mode
		html = win.parentWindow.$(win.parentDocument.getElementsByTagName('html')[0])
		
		if(html.scrollTop)
		{
			y += html.scrollTop;
		}
		if(html.scrollLeft)
		{
			x += html.scrollLeft;
		}
		
		if(x < 0)
		{
			x = 0;
		}
		if(y < 0)
		{
			y = 0;
		}
		
		x -= win.getBoxBoundary(win.win, 'left');
		y -= win.getBoxBoundary(win.win, 'top'); 
		
		//console.info('top: ' + y + ', left: ' + x);
		
		return {top: y,left: x};
	},
	
	calcOffset: function(pos, offset)
	{
		if(this.windows.length && offset)
		{
			pos.top += offset.y;
			pos.left += offset.x;
		}
		return pos;
	},
	
	getPosInt: function(nr)
	{
		return Math.abs(parseInt(nr));
	},
	
	onScroll: function(e)
	{
		Event.stop(e);	
	},
	
	myDebug: function(text)
	{
		elem = $('debug');
		
		if(elem.firstChild)
		{
			elem.insertBefore(document.createElement("br"),elem.firstChild);
			elem.insertBefore(document.createTextNode(text),elem.firstChild);
		}
	}	
};


if(window == window.top)
{
	var WindowFactory = new myWindowFactory();
}
else
{
	var WindowFactory = window.top.WindowFactory;
}

document.writeln('<link rel="stylesheet" type="text/css" href="'+WindowFactory.baseUrl+'/css/windowFactory.css">');


var myWindow = Class.create();
myWindow.prototype = {

	win: null,
	closed: null,
	inline: null,
	callback: null,
	lockBackground: null,
	offset: null,
	windowName: null,
	parentDocument: null,
	parentWindow: null,
	contentWindow: null,
	zIndex: null,
	selectsDisabled: null,
			
	initialize: function(target, name, o)
	{
		//debugger;
		
		var ws = WindowFactory.settings;
		
		this.inline = o && typeof o.inline == 'boolean'?o.inline:ws.inlineMode;
		this.callback = o && o.callback?o.callback:ws.callback;
		this.lockBackground = o && typeof o.lockBackground == 'boolean'?o.lockBackground:ws.lockBackground;
			
		this._closePopup = this.closePopup.bindAsEventListener(this);
		Event.observe(window, "unload", this._closePopup);
		
		var count = WindowFactory.windows.length;
		
		if(count && (o && typeof o.positionOffset == 'boolean'?o.positionOffset:ws.positionOffset))
		{
			var x = o && o.offsetX?o.offsetX:ws.offsetX;
			var y = o && o.offsetY?o.offsetY:ws.offsetY;
			
			this.offset = {x: count * x, y: count * y};	
		}
		
		var width = WindowFactory.getPosInt(o && o.width?o.width:ws.width);
		var	height = WindowFactory.getPosInt(o && o.height?o.height:ws.height);
		var	size = {w:width, h:height};
		
		if(this.inline)
		{
			var resizeable, draggable;
			
			if(resizeable = (o && typeof o.resizeable == 'boolean'?o.resizeable:ws.resizeable))
			{	
				this._onStartResize = this.onStartResize.bind(this);
				this._onResize = this.onResize.bind(this);
				this._onEndResize   = this.onEndResize.bind(this);
			}
			
			if(draggable = (o && typeof o.draggable == 'boolean'?o.draggable:ws.draggable))
			{
				this._onStartDrag = this.onStartDrag.bind(this);
				this._onDrag = this.onDrag.bind(this);
				this._onEndDrag = this.onEndDrag.bind(this);
			}
			
			this._onBrowserResize = this.onBrowserResize.bind(this);
			Event.observe(window, "resize", this._onBrowserResize);
			
			this._onWindowScroll = this.onWindowScroll.bind(this);
			Event.observe(window, "scroll", this._onWindowScroll);
			
			this.openInlinePopup(target, name, size, draggable, resizeable, o)
		}
		else
		{
			this.openPopup(target, name, size, o);
		}
	},
	
	windowClosed: function()
	{
		return this.win.closed;
	},
	
	commitCallback: function(args)
	{
		if(this.callback)
		{
			this.callback(args);
		}
	},
	
	closePopup: function(event)
	{
		if(this.win)
		{
			if(this.inline)
			{
				if(!this.closed)
				{
					this.win.remove();
					WindowFactory.decZIndex();
				}
			}
			else
			{
				if(!this.closed)
				{
					this.win.close();
				}
			}
			
			this.closed = true;
		}
	},
	
	openPopup: function(target, name, size, options)
	{
		var pos = WindowFactory.calcPosition(this, size.w, size.h);
		
		pos = WindowFactory.calcOffset(pos, this.offset);
		
		this.windowName = this.buildWindowName(name);
		
		options = '';
		options += 'width=' + size.w + ',height=' + size.h; 
		options += ',' + "top=" + pos.top + ",left=" + pos.left;
		
		this.win = window.open(target,this.windowName,options);
		this.closed = this.win.closed;
	},
	
	openInlinePopup: function(target, name, size, draggable, resizeable, o)
	{
		var width,height,top,left,win;
		
		target = "src='"+target+"'";
		
		this.windowName = this.buildWindowName(name);		
		
		if(size)
		{
			width = 'width:'+size.w+'px;';
			height = 'height:'+size.h+'px;';
		}
		
		var closeFunction = 'WindowFactory.settings.closeFunction';
		
		if(o && typeof o.closeFunction == 'string')
		{
			closeFunction = o.closeFunction;
		}
		
		if(o && typeof o.parentWindow == 'object')
		{
			this.parentWindow = o.parentWindow;
			this.parentDocument = o.parentWindow.document;
		}
		else
		{
			this.parentWindow = window;
			this.parentDocument = window.document;
		}
		
		var ts = this.getTimestamp();
		var ws = WindowFactory.settings; 
		
		var containerId = ws.containerIdPart + '_' + ts;
		var contentId = ws.contentIdPart + '_' + ts;
		var contentLockId = ws.contentLockIdPart + '_' + ts;
		var topId = ws.topIdPart + '_' + ts;
		var middleId = ws.middleIdPart + '_' + ts;
		var bottomId = ws.bottomIdPart + '_' + ts;
		
		var containerClass = o && o.containerClass?o.containerClass:ws.containerClass;
		if( WindowFactory.isIE6)
		{
			containerClass = o && o.containerClassIE6?o.containerClassIE6:ws.containerClassIE6;
		}
		var topClass = o && o.topClass?o.topClass:ws.topClass;
		var middleClass = o && o.middleClass?o.middleClass:ws.middleClass;
		var contentClass = o && o.contentClass?o.contentClass:ws.contentClass;
		var contentLockClass = o && o.contentLockClass?o.contentLockClass:ws.contentLockClass;
		var bottomClass = o && o.bottomClass?o.bottomClass:ws.bottomClass;
		
		var closeText = o && o.closeText?o.closeText:ws.closeText;
		var closeAltTitle = o && o.closeAltTitle?o.closeAltTitle:ws.closeAltTitle;
		
		var closeClass = o && o.closeClass?o.closeClass:ws.closeClass;
		if( WindowFactory.isIE6)
		{
			closeClass = o && o.closeClassIE6?o.closeClassIE6:ws.closeClassIE6;
		}
		
		if(WindowFactory.inlineWindowTemplate)
		{
			win = WindowFactory.inlineWindowTemplate;
		}
		else
		{
			var cLockBg, bg;
			if( bg = o && o.contentLockBgImg?o.contentLockBgImg:ws.contentLockBgImg)
			{
				cLockBg = 'background:url('+WindowFactory.baseUrl+'/'+bg+') repeat;';				
			}
			else
			{
				cLockBg = 'background-color: white;opacity:0;filter: alpha(opacity=0);';
			}
			
			this.zIndex = WindowFactory.incZIndex();
			
			win = 	"<div id='"+containerId+"' class='"+containerClass+"' style='position:absolute;z-index:"+this.zIndex+";display:none;'>"+
				  		"<div id='"+topId+"' class='"+topClass+"'>";
			
			if(draggable)
			{
				var dragHandleId = ws.dragHandleIdPart + '_' + ts;
				var dragHandleClass = o && o.dragHandleClass?o.dragHandleClass:ws.dragHandleClass;
				win += "<div id='"+dragHandleId+"' class='"+dragHandleClass+"' style='width:100%;height:100%;cursor:move;'>"+									
								"<span style='padding-left:5px;'>" + name + "</span>"+
							"</div>";
			}
							
			//win +=				"<a href='javascript:void(0);' class='"+ closeClass +"' onclick='WindowFactory.closePopup(\""+this.windowName+"\");return false;' title='"+closeAltTitle+"'>"+
			win +=				"<a href='javascript:void(0);' class='"+ closeClass +"' onclick='" + closeFunction + "(\""+this.windowName+"\");return false;' title='"+closeAltTitle+"'>"+
								closeText +
								"</a>"+
						"</div>"+
						"<div id='"+middleId+"' class='"+middleClass+"'>"+
							"<div id='"+contentId+"' class='"+contentClass+"' style='position:relative;bottom:0px;"+width+height+"'>"+
								"<div id='"+contentLockId+"' class='"+contentLockClass+"' style='position:absolute;top:0px;bottom:0px;width:100%;height:100%;z-index:"+WindowFactory.incZIndex()+";"+cLockBg+"display:none;'></div>" +
								"<iframe name='"+this.windowName+"' "+target+" style='width:100%;height:100%;' frameborder='0'></iframe>"+
							"</div>"+
						"</div>"+
						"<div id='"+bottomId+"' class='"+bottomClass+"' style='width:100%;position:relative;'>"; 
			if(resizeable)
			{
				var resizeHandleId = ws.resizeHandleIdPart + '_' + ts;
				var resizeHandleClass = o && o.resizeHandleClass?o.resizeHandleClass:ws.resizeHandleClass;
								
				var orientation='', cursor;
				
				if(o && typeof o.resizeY == 'boolean'?o.resizeY:ws.resizeY)
				{
					orientation += 's';
				}
				if(o && typeof o.resizeX == 'boolean'?o.resizeX:ws.resizeX)
				{
					orientation += 'e';
				}
				if(!orientation)
				{
					orientation = 'se-resize';
				}
				else
				{
					orientation += '-resize';
				}
				
				cursor = 'cursor:'+orientation+';';
				
				win += "<div id='"+resizeHandleId+"' class='"+resizeHandleClass+"' style='float:right;"+cursor+";'>"+
							"</div>";
			}				
							
							
			win +=			"</div>"+
					"</div>";
		}
		
		var body = this.parentDocument.getElementsByTagName("body")[0];
		new Insertion.Top(body,win);
		
		var pw = this.parentWindow;
		
		this.win = pw.$(containerId);
		this.content = pw.$(contentId);
		this.contentWindow = pw.frames[this.windowName];
		
		//TODO refine calculation of window size (margin, border, padding) and position
		//var winWidth = size.w + parseInt(pw.$(middleId).getStyle('padding-left')) + parseInt(pw.$(middleId).getStyle('padding-right'));
		//var winHeight = size.h + parseInt(pw.$(topId).getStyle('height')) + parseInt(pw.$(bottomId).getStyle('height'));
		
		var iframeElem = this.content.down('iframe');
		var topElem = pw.$(topId);
		var bottomElem = pw.$(bottomId);
		
		var winWidth = size.w + this.getBoxBoundariesX(pw.$(middleId)) + this.getBoxBoundariesX(this.content) + this.getBoxBoundariesX(iframeElem);
		var winHeight = size.h + parseInt(topElem.getStyle('height')) + this.getBoxBoundariesY(topElem) + parseInt(bottomElem.getStyle('height')) + this.getBoxBoundariesY(bottomElem) + this.getBoxBoundariesY(pw.$(middleId)) + this.getBoxBoundariesY(this.content) + this.getBoxBoundariesY(iframeElem);
		
		this.win.style.width = winWidth + 'px';
		this.win.style.height = winHeight + 'px';
		
		var pos = WindowFactory.calcPosition(this, winWidth, winHeight);
		
		pos = WindowFactory.calcOffset(pos, this.offset);
		
		this.win.style.top = pos.top+'px';
		this.win.style.left = pos.left+'px';
		
		this.win.style.display = 'block';
				
		this.contentLock = pw.$(contentLockId);
		this.contentStartWidth = size.w;
		this.contentStartHeight = size.h;
		this.winStartWidth = winWidth;
		this.winStartHeight = winHeight;
		this.pointerStartPosX = null;
		this.pointerStartPosY = null;
		this.winStartPos = null;
		
		if(draggable)
		{
			var oSD = this._onStartDrag;
			var oD = this._onDrag;
			var oED = this._onEndDrag;
			
			new pw.Draggable(containerId,{handle: dragHandleId, starteffect:null, endeffect:null, onStart: oSD, onDrag: oD, onEnd: oED});
		}
		
		if(resizeable)
		{
			var oSR = this._onStartResize;
			var oR = this._onResize;
			var oER = this._onEndResize;
			var constraint = null;
			
			if((o && typeof o.resizeX == 'boolean'?o.resizeX:ws.resizeX) && !(o && typeof o.resizeY == 'boolean'?o.resizeY:ws.resizeY))
			{
				constraint = 'horizontal';
			}
			if(!(o && typeof o.resizeX == 'boolean'?o.resizeX:ws.resizeX) && (o && typeof o.resizeY == 'boolean'?o.resizeY:ws.resizeY))
			{
				constraint = 'vertical';
			}
			
			//TODO if constraint = vertical, center resizeHandle
			
			new pw.Draggable(resizeHandleId,{constraint: constraint,starteffect:null, endeffect:null, onStart: oSR, onDrag: oR, onEnd: oER});
		}
		
		this.closed = false;
	},

	onStartResize: function(element,event)
	{
		this.contentLock.style.display = 'block';
				
		this.winStartWidth = parseInt(this.win.getStyle('width'));
		this.winStartHeight = parseInt(this.win.getStyle('height'));
		
		this.contentStartWidth = parseInt(this.content.getStyle('width'));
		this.contentStartHeight = parseInt(this.content.getStyle('height'));
		
		this.startPosX = Event.pointerX(event);
		this.startPosY = Event.pointerY(event);
		
		this.parentDocument.body.ondrag = function () { return false; };
		this.parentDocument.body.onselectstart = function () { return false; };
	},
	
	onResize: function(element,event)
	{
		var startPosX = this.startPosX;
		var startPosY = this.startPosY;
		
		var dWidth = Event.pointerX(event) - startPosX;
		var dHeight = Event.pointerY(event) - startPosY;
		
		var winWidth = this.winStartWidth + dWidth;
		var winHeight = this.winStartHeight + dHeight;
		
		var contentWidth = this.contentStartWidth + dWidth;
		var contentHeight = this.contentStartHeight +dHeight;
				
		if(winWidth < WindowFactory.settings.minWidth || winHeight < WindowFactory.settings.minHeight)
		{
			return;
		}
		
		this.content.style.width = contentWidth + 'px';
		this.win.style.width = winWidth + 'px';
		this.content.style.height = contentHeight + 'px';
		this.win.style.height = winHeight + 'px';
	},
	
	onEndResize: function(element,event)
	{
		this.contentLock.style.display = 'none';
		
		Event.element(event).style.left = '';
		Event.element(event).style.top = '0px';
		Event.element(event).style.bottom = '0px';
		Event.element(event).style.right = '0px';
		
		this.parentDocument.body.ondrag = null;
    	this.parentDocument.body.onselectstart = null;
	},
	
	onStartDrag: function()
	{
		this.contentLock.style.display = 'block';
		this.parentDocument.body.ondrag = function () { return false; };
		this.parentDocument.body.onselectstart = function () { return false; };
	},
	
	onDrag: function()
	{
		/*
		var x = parseInt(this.win.getStyle('left'));
		var y = parseInt(this.win.getStyle('top'));
		
		x += this.getBoxBoundary(this.win, 'left');
		y += this.getBoxBoundary(this.win, 'top');
		
		if(x <= 0)
		{
			return;
		}
		if(y < 0)
		{
			return;
		}
		*/
	},
	
	onEndDrag: function()
	{
		this.contentLock.style.display = 'none';
		this.parentDocument.body.ondrag = null;
    	this.parentDocument.body.onselectstart = null;
	},
	
	onBrowserResize: function(e)
	{
		this.repositionWindow(e);
	},
	
	onWindowScroll: function(e)
	{
		this.repositionWindow(e);
	},
	
	repositionWindow: function()
	{
		if(this.win && !this.closed)
		{
			var width = parseInt(this.win.getStyle('width'));
			var height = parseInt(this.win.getStyle('height'));
			var pos = WindowFactory.calcPosition(this, width, height);
			pos = WindowFactory.calcOffset(pos, this.offset);
			this.win.style.left = pos.left + 'px';
			this.win.style.top = pos.top + 'px';
		}
	},
		
	getTimestamp: function()
	{
		if(!this.timestamp)
		{
			this.timestamp = new Date().getTime();
		}
		
		return this.timestamp; 
	},
	
	getBoxBoundariesX: function(box)
	{
		var rB = this.getBoxBoundary(box, 'right');
		var lB = this.getBoxBoundary(box, 'left');
		
		return rB + lB;
	},
	
	getBoxBoundariesY: function(box)
	{
		return this.getBoxBoundary(box, 'top') + this.getBoxBoundary(box, 'bottom');
	},
	
	getBoxBoundary: function(box, dir)
	{
		box = $(box);
		boxBoundary = parseInt(box.getStyle('margin-'+dir)) + parseInt(box.getStyle('border-'+dir+'-width')) + parseInt(box.getStyle('padding-'+dir)) ; 
		return boxBoundary?boxBoundary:0;
	},
	
	buildWindowName: function(winName)
	{
		return winName.replace(/\s/g,'')+'_'+this.getTimestamp(); 
	}
};