KWindow = {
	id : window.location.href+"_"+(new Date().getTime())
	, open : function(sUrl, options) {
		var originalOptions = Object.extend({},options);
		var sWinName = "kWindow"+(new Date().getTime());
		var iHeight = options.height;
		var iWidth = options.width;
		var sActionScript = options.actionScript || null;
		var winOpener = options._opener || window;
		options._opener = null;
		this._prepareCallbackFunctions(sWinName,options,winOpener);
		var bModal = options.modal;
		options.modal = options.modal ? "true" : "false";
		options.name = null;
		options.height = null;
		options.width = null;
		options.actionScript = null;
		var sParams = this._encodeParams(options);
		if(sUrl.indexOf("?") < 0) {
			sUrl += "?";
		} else {
			sUrl += "&";
		}
		var win = new Window({
			id : sWinName
			, title: decodeURIComponent(options.title || "")
			, url: sUrl+sParams
			, width: iWidth
			, height: iHeight
			, minimizable: false
			, maximizable: false
			, showEffectOptions: {duration: 0.15}
			, hideEffectOptions: {duration: 0.15}
			, parent: window.top.document.body
			, destroyOnClose: true
		});
		win._opener = winOpener;
		win.showCenter(bModal);
		var eWinContentFrame = Element.getElementsBySelector(win.element,"iframe#"+win.getId()+"_content")[0];
		Event.observe(eWinContentFrame,"load",this._newContentLoadCallback(originalOptions,win));
		eWinContentFrame._kWindow = win;
	}
	, dialog : function(options) {
		var sUrl = options.kWindowUrl || KBase.toFullUrl("/popup/KDialog.html");
		this.open(sUrl,options);
	}
	, confirm : function(options) {
		var sUrl = options.kWindowUrl || KBase.toFullUrl("/popup/KConfirm.html");
		if(typeof options.modal == "undefined") {
			options.modal = true;
		}
		options.onComplete = options.onComplete || options.actionScript;
        if (options.width && options.height) {
            sUrl = sUrl+"?winwidth="+options.width+"&winheight="+options.height;
        }
        else if (options.width) {
            sUrl = sUrl+"?winwidth="+options.width;
        }
        else if (options.height)  {
            sUrl = sUrl+"?winheight="+options.height;
        }
		this.open(sUrl,options);
	}	
	, getOpener : function() {
		var pWin = this.getCurrentPopupWindow();
		//PHD 8/6/2007 - First try to get the opener reference on the Window instance
		if(pWin && pWin._opener) return pWin._opener;
		//PHD 8/6/2007 - Just punt and say the top window was the opener
		if(window == window.top) {
			if(window.opener) {
				return window.opener;
			}
		}
		return window.top;
	}
	, reloadOpener : function() {
		var winOpener = this.getOpener();
		winOpener.location.href = winOpener.location.href;
	}
	, close : function(sWinId) {
		if(typeof Windows != 'undefined') {
			if(sWinId) {
				Windows.close(sWinId);				
			} else {
				Windows.closeAll();
			}
		} else {
			var kWindow = this.getCurrentPopupWindow();
			if(kWindow) {
				kWindow.close();
			}
		}
	}
	, closeAndReload : function() {
		this.close();
		this.reloadOpener();
	}
	, callOnComplete : function() {
		var pWin = this.getCurrentPopupWindow();
		var oOriginalWin = this.getOpener();
		if(pWin && oOriginalWin) {
			var arrCallbackArgs = [pWin.getId(),"onComplete"];
			for(var i=0; i<arguments.length; i++) {
				arrCallbackArgs.push(arguments[i]);
			}
			var origKWindow = oOriginalWin.KWindow;
			origKWindow.doCallback.apply(origKWindow,arrCallbackArgs);
		}
	}
	, doCallback : function(sWinName, sFunctionKey) {
		var fCallback = this._getCallbackRegistry().getCallbackFunction(sWinName,sFunctionKey,true);
		if(fCallback) {
			var arrFuncArgs = [];
			if(arguments.length > 2) {
				for(var i=2; i<arguments.length; i++) {
					arrFuncArgs.push(arguments[i]);
				}
			}
			return fCallback.apply({},arrFuncArgs);
		}
	}
	, getCurrentPopupWindow : function() {
			//PHD 7/20/2007 - Since the location of the _kWindow attribute is not 
			//always the same relative to the content of the popup which is calling 
			//this function, try several locations to find the right one.
			var arrPossKWindows = [
				function() { return window.parent.frameElement._kWindow} //Dialog with frameset
				, function() { return window.frameElement._kWindow } //Popup in iframe
				, function() { return window.document._kWindow } //Last resort
			];
			for(var i=0; i<arrPossKWindows.length; i++) {
				try {
					var oWin = arrPossKWindows[i]();
					if(typeof oWin != "undefined") {
						return oWin;
					}
				} catch(ex) {}
			}	
			return null;
	}
	, _newContentLoadCallback : function(opts,win) {
		return function() {
			var eIFrame = Element.getElementsBySelector(win.element,"iframe#"+win.getId()+"_content")[0];
			if(eIFrame) {
				eIFrame.contentWindow._kWindow = win;
				//PHD 7/20/2007 - FF, IE and Safari have slightly different ways of getting the document
				var eDocument = eIFrame.contentDocument || eIFrame.contentWindow.document;
				if(eDocument) {
					eDocument._kWindow = win;
					if(!opts.title) {
						win.setTitle(eDocument.title); 
					}					
				}
			}	
		}
	}
	, _encodeParams : function(oParams, arrNames) {
		var arrParams = new Array();
		if(arrNames) {
			for(var i=0; i<arrNames.length; i++) {
				var sName = arrNames[i];
				var sValue = oParams[sValue];
				if(sValue || (typeof sValue == 'string')) {
					arrParams.push(this._encodeParam(sName,sValue));
				}
			}
		} else {
			for(var sName in oParams) {
				var sValue = oParams[sName];
				if(sValue || (typeof sValue == 'string')) {
					arrParams.push(this._encodeParam(sName,sValue));
				}
			}
		}
		return arrParams.join("&");
	}
	, _encodeParam : function(sName, sValue) {
		return sName+"="+sValue;
	}
	, _prepareCallbackFunctions : function(sWinName,options,bindWindow) {
		if(!options.onComplete) return;
		var fOnComplete = null;
		if(typeof options.onComplete != "string") {
			fOnComplete = options.onComplete;				
		} else {
			var sOnCompleteCode = options.onComplete;
			fOnComplete = function() {
				//PHD 10/4/2007 - Ensure code is run in requested window
				bindWindow.eval(sOnCompleteCode);
			}
		}
		this._getCallbackRegistry().registerCallbackFunction(sWinName,"onComplete",fOnComplete);
		options.onComplete = "KWindow.doCallback('"+sWinName+"','onComplete');";
	}
	, _getCallbackRegistry : function() {
		return window.top.KWindowCallbackRegistry;
	}
}
if(typeof Window != "undefined") {
	//PHD 7/21/2007 - Ensures that multiple modal windows can be stacked on top of each other
	Window.keepMultiModalWindow = true;
}
if(window.top != window && window.top.KWindow) {
	//PHD 7/21/2007 - Routes open requests to top level KWindow so that dialogs 
	//opened from within dialogs (which exist in iframes) are able to function correctly
	KWindow._window = window;
	KWindow.open = function(sUrl,options){
		options._opener = this._window;
		window.top.KWindow.open(sUrl,options);
	};
}
if(typeof window.top.KWindowCallbackRegistry == "undefined") {
	window.top.KWindowCallbackRegistry = {
		registerCallbackFunction : function(sWinName, sCallbackName, fCallback) {
			var callbackMap = this._getCallbackFunctionsByKWindow()[sWinName];
			if(!callbackMap) {
				callbackMap = {};
				this._getCallbackFunctionsByKWindow()[sWinName] = callbackMap;
			}
			callbackMap[sCallbackName] = fCallback;
		}
		, getCallbackFunction : function(sWinName, sCallbackName) {
			var callbackMap = this._getCallbackFunctionsByKWindow()[sWinName];
			if(!callbackMap) return null;
			return callbackMap[sCallbackName];
		}
		, _getCallbackFunctionsByKWindow : function() {
			if(!this.callbackFunctionsByKWindow) {
				this.callbackFunctionsByKWindow = {};
			}
			return this.callbackFunctionsByKWindow;
		}
	}
}
