/*--------------------------------------
	kUI - K2 User Interface Library
	Author: (r.Baron 2/2009)
	Copyright (c) 2009 Edulence Corp.
  --------------------------------------*/

Element.addMethods({
	appendText: function(element, text) {
		element = $(element);
		text = String.interpret(text);
		element.appendChild(document.createTextNode(text));
		return element;
	},
	setScrollOffset: function(element, offset) {
		element = $(element);
		if (arguments.length == 3) { offset = { left: offset, top: arguments[2] }; }
		element.scrollLeft = offset.left;
		element.scrollTop  = offset.top;
		return element;
	},
	getScrollDimensions: function(element) { 
		return { width:$(element).scrollWidth, height:$(element).scrollHeight };
	}
});

Object.extend(document.viewport, {
	getScrollOffset: document.viewport.getScrollOffsets,
	setScrollOffset: function(offset) { Element.setScrollOffset(Prototype.Browser.WebKit ? document.body : document.documentElement, offset); },
	getScrollDimensions: function() { return Element.getScrollDimensions(Prototype.Browser.WebKit ? document.body : document.documentElement); }
});

Prototype.Browser.IE6 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5),10)==6;
Prototype.Browser.IE7 = Prototype.Browser.IE && !Prototype.Browser.IE6;

var kUI = { 
	winMngr: null,
	openWin : function(options) {
		if (options.src) {
			winOptions = {
				theme : options.theme || 'hClr',
				title : options.title || '',
				src   : options.src
			};
			var newWin = new kUI.Window(winOptions);
		}
	},

	inBounds: function(options) {
		if (options.width) {
			var winDims = document.viewport.getDimensions(), defWidth = 790;
			options.width = (options.width) ? (Number(options.width)>(winDims.width-60)) ? winDims.width-60 : Number(options.width) : defWidth;
			if (options.height) {
				options.height	= (Number(options.height)>(winDims.height-60)) ? (winDims.height-60) : Number(options.height);
			}
		}
		return options;
	}
};

kUI.WindowManager = Class.create({
	options: {
		container:   null, // will default to document.body
		zIndex:      500000
	},

	initialize: function(options) {	
		this.options = Object.extend(this.options, options || {});
		this.container = $(this.options.container || document.body);
		if (this.container === $(document.body)) {
			this.viewport = document.viewport;
			this.scrollContainer = window;
		} else { this.viewport = this.scrollContainer = this.container; }
		this.stack = new kUI.WindowManager.Stack();
		this.Sessions = 0;
	},
  
	destroy: function() {
		this.windows().invoke('destroy');
		this.stack.destroy();
	},
	
	activeWindow : function() { return (this.stack.windows.size()>0) ? true : false; },
	
	topCaller : function() {
		 if (this.stack.windows.size()>0) { return (this.stack.windows.last().options.dataObj) ? true : false; }
		 else { return false; }
	},
  	
  	callerObject : function() {
  		return (this.stack.windows.size()>0) ? this.stack.windows.last().options.dataObj : {};
	},
  	
  	getWindow : function() {
  		return (this.stack.windows.size()>0) ? this.stack.windows.last() : null;
	},
  	
	handleCaller : function(Obj) {
		if (this.stack.windows.size()===0) { return; }
		var activeWin = this.stack.windows.last();
		Obj = Object.extend(Obj, activeWin.options.dataObj || {});
		if (activeWin.options.dataObj.callingFunc) { activeWin.options.dataObj.callingFunc(Obj); }
		else { if (activeWin.options.caller.childInvoke) { activeWin.options.caller.childInvoke(Obj); }}
	},
  
	removeOverflow: function(retainOverflow) {
		var activeWin = this.getWindow();
		if (!retainOverflow) {
			var container = this.container;
			activeWin.options.savedOverflow = container.style.overflow || "auto";
			activeWin.options.savedOffset  = this.viewport.getScrollOffset();
			container.setStyle({overflow:"hidden"});
			
			if (Prototype.Browser.IE) { 
				container.document.getElementsByTagName('html')[0].style.overflow = 'hidden';
				container.document.body.scroll = 'no';
			}
			
			if (activeWin.options.maximize) { this.viewport.setScrollOffset({top:0,left:0}); }
		}
	},

	resetOverflow: function(retainOverflow) {
		var activeWin = this.getWindow();
		if (!retainOverflow) {
			var container = this.container;
			if (activeWin.options.savedOverflow) {
				if (Prototype.Browser.IE) { 
					container.document.getElementsByTagName('html')[0].style.overflow = 'auto'; 
					container.document.body.scroll = 'yes';
				}
				if (activeWin.options.maximize) {
					container.style.overflow = activeWin.options.savedOverflow;
					this.viewport.setScrollOffset(activeWin.options.savedOffset);
					activeWin.options.savedOffset = activeWin.options.savedOverflow = null;
				}
			}
		}
	},
	
	register: function(win) { this.stack.add(win); this.options.zIndex++; },
	unregister: function(win) { this.stack.remove(win); this.options.zIndex--; }
});

kUI.WindowManager.Stack = Class.create(Enumerable, {
	initialize: function() { this.windows = [ ]; },
	add: function(win, position) { this.windows.splice(position || this.windows.length, 0, win); },
	remove: function(win) { this.windows = this.windows.without(win); },
	each: function(iterator) { this.windows.each(iterator); },
	getPosition: function(win) { return this.windows.indexOf(win); },
	setPosition: function(win, position) { this.remove(win); this.windows.splice(position, 0, win); },
	getFrontWindow: function() { return this.windows.last(); },
	getBackWindow: function() { return this.windows.first(); },
	getPreviousWindow: function(win) { return (win == this.windows.first()) ? null : this.windows[this.windows.indexOf(win) - 1]; }
});

kUI.Popup = Class.create({
	options : {},
	
	initialize: function(options) {
		var defOptions = {
			caller:			window,
		    width:         	790,
		    height:        	590
		};
		this.options = Object.extend(defOptions, options || {});
		var popup = this.options;
		var popUrl = (popup.srcObj) ? popup.srcObj.readAttribute('href') || '' : '';
		
		if (!popUrl.empty())
		{
			winDims = { width: screen.availWidth, height: screen.availHeight };
			kWidth	= (popup.width)  ? (Number(popup.width)>(winDims.width-60))   ? (winDims.width-60)  : Number(popup.width)  : 790;
			kHeight	= (popup.height) ? (Number(popup.height)>(winDims.height-60)) ? (winDims.height-60) : Number(popup.height) : 590;
			popup.options.width = kWidth;
			popup.options.height = kHeight;
			var popOptions = (popup.options) ? Object.toQueryString(popup.options).gsub('&',',') : '';
			var posX = 0, posY = 0;
			if (kWidth && kHeight) {
				if (kWidth<winDims.width) 	{ posX = Math.floor((winDims.width-Number(kWidth))/2,0); }
				if (kHeight<winDims.height) { posY = Math.floor((winDims.height-Number(kHeight))/2,0); }
				if (!popOptions.empty()) 	{ popOptions += ',left='+posX+',top='+posY; }
			}
			var popWin = window.open(popUrl, "portalWin", popOptions);
			if (!popWin) { alert('Popup Blocker encountered, Please try again!'); } else { popWin.focus(); }
		}
	}
});

kUI.Window = Class.create({
	options : {},
	
	initialize: function(options) {
		var defOptions = {
			ajax:			null,
			id: 			null,
			windowManager: 	null,
			caller:			window,
			top:           	0,
		    left:          	0,
		    width:         	790,
		    height:        	450,
		    shadow:			false,
		    overlay:		null,
		    shaded:			true,
		    close:			true,
			closeBtn:		false,
		    zIndex:			null,
		    theme:			'hBox'
		};
		this.options = Object.extend(defOptions, options || {});

		//Register Event Callbacks
		this.handlers = (options.callback) ? options.callback : {};
		if (this.options.srcObj) { this.options.src = $(this.options.srcObj).readAttribute('href'); }
		if (this.options.timer) { this.setTimer(this.options.timer); }
		
		this.windowManager = kUI.winMngr;
		this.windowManager.register(this);
		this.options.zIndex = this.windowManager.options.zIndex;
		
		if (this.options.maximize || Prototype.Browser.IE) { this.windowManager.removeOverflow(this.options.retainOverflow); }
		if (!this.options.maximize) { this.createOverlay(); }
		else {
			var vpDims = document.viewport.getDimensions();
		 	this.options.width  = vpDims.width;
		 	this.options.height = vpDims.height;
		 	this.options.shaded = false;
		 	this.options.theme 	= 'hMax'; 
		}

		if (this.options.overlayOnly) { return; }
		
		this.create();
		this.id = this.element.id;

		//Hide Flash Content from Macs
		if (navigator.userAgent.indexOf("Mac")!=-1) { var flashMods = $$('div.flashModule').each(function(idx){idx.setStyle({visibility:'hidden'});}); }

		this.render();
	},
  
  	callback: function(event, options) {
		//if (window.console) { console.log(event); console.log(options); }
		if (this.handlers[event]) { this.handlers[event](options||{}); }
	},

	overlayClicked : function() { 
		if (this.options.overconfirm) { if (!confirm('Are you sure you wish to close this window?')) { return; }}
		if (this.options.overfunction) { this.options.overfunction(); }
		this.callback('overlay:onClick',null);
		this.close(); 
	},
	createOverlay : function() {
		var ovDims = kUI.winMngr.viewport.getDimensions();
        //var bodyElm = Prototype.Browser.WebKit ? document.body : document.documentElement;
		var bodyDims = $(document.body).getDimensions();
		var height = (ovDims.height>bodyDims.height) ? ovDims.height : (bodyDims.height+20);
		this.overlay = this.createDiv("overlay", {	
      		style: "height:"+height+"px;width:"+ovDims.width+"px;z-index:"+this.options.zIndex
    	});
    	if (!this.options.shaded) { $(this.overlay).addClassName('clear'); }
		this.overlay.identify();
		
		if (this.options.close) {
			this.overlay.observe("click", this.overlayClicked.bind(this))
						.observe("mousewheel", 		function(event){ Event.stop(event);}, false)
						.observe("DOMMouseScroll", 	function(event){ Event.stop(event);}, false);
		} else {
		 	this.overlay.setStyle({cursor:'default'});
		}
		this.addElements(this.overlay);
	},
  
	render: function() {
		this.addElements(this.element);
		this.setBounds(this.options);
		this.visible = true;
		if (this.options.onload) { this.options.onload(); }
		this.callback('window:load',null);
	},
	
	setTimer : function (timer) { 
		var defTime = (!timer) ? 2800 : timer;
		if (defTime!=="") { 
			this.options.timeoutObj = window.setTimeout(function(){ if (this && this.visible) { 
				if (this.options.timeoutObj) { window.clearTimeout(this.options.timeoutObj); }
				this.close(); 
			}}.bind(this), defTime); }
	},
  
	close: function(event, options) {
		if (event) { event.stop(); }
		if (this.options.confirm) { if (!confirm('Are you sure you wish to close this window?')) { return; }}
		if (this.options.maximize || Prototype.Browser.IE) { this.windowManager.resetOverflow(this.options.retainOverflow); }
		this.hide();
		if (this.overlay) { this.overlay.remove(); }
		
		//Show Flash Content for Macs
		if (navigator.userAgent.indexOf("Mac")!=-1) { var flashMods = $$('div.flashModule').each(function(idx){$(idx).setStyle({visibility:'visible'});}); }
		
		this.windowManager.unregister(this);
		if (this.options.reload===true) { klGeneric.pageRefresh(); }
		if (this.options.onclose) { this.options.onclose(); }
		this.callback('window:close',options || {});
	},
  
	setCenter: function(options) {
		var size      = this.element.getScrollDimensions(),
		viewport      = this.windowManager.viewport;
		viewportArea  = viewport.getDimensions();
		this.options.top  = (viewportArea.height - size.height) / 2;
		this.options.left = (viewportArea.width  - size.width)  / 2;
		
		var kTop  = ((this.options.maximize) ? 0 : (this.options.top>0) ? this.options.top : 5);
		var kLeft = ((this.options.left>0) ? this.options.left : (this.options.maximize) ? 0 : 5);
		
		if (Prototype.Browser.IE6) { 
			this.element.setStyle({position:'absolute'}); 
			scrollDims = document.viewport.getScrollOffset();
			kTop = kTop+scrollDims[1];
		}
		this.element.setStyle({top:kTop+'px',left:kLeft+'px'});
	},
	
	setBounds: function(options) { 
		this.validateBounds(options);
		if (options.height) { $(this.content).setStyle({ height:options.height+'px' });  }
		if (options.width) 	{ $(this.element).setStyle({ width:options.width+'px' }); }
		this.setCenter();
	},
	
	validateBounds: function(options) {
		if (!options.maximize) {
			var winDims = document.viewport.getDimensions(), kWidth, kHeight;
			this.options.width  = (options.width) ? (Number(options.width)>(winDims.width-60)) ? (winDims.width-60)  : Number(options.width)+12 : 790; //14= Padding+Borders [5px Padding]
			if (options.height) {
				this.options.height	= (Number(options.height)>(winDims.height-60)) ? (winDims.height-60) : Number(options.height);
			}
		}
	},
	
	create: function() {
		this.element = new Element('div', { 
			className:'kWin '+this.options.theme,
			id: this.options.id,
			style: "top:-10000px;left:-10000px;z-index:"+(this.options.zIndex+1)
		});
		this.validateBounds(this.options);
		
		this.wrapperHead 	= new Element('div',{className:'kwinTL'}).insert(new Element('div',{className:'kwinTR'}));
		this.wrapperCnt 	= new Element('div',{className:'kwinCnt'});
		this.wrapperFoot 	= new Element('div',{className:'kwinBL'}).insert(new Element('div',{className:'kwinBR'}));
		
		var titleTxt = this.options.title || ' ';
		this.header  = new Element('div',{className:'titlebar'}).update(unescape(titleTxt));
		
		if (this.options.close && !this.options.closeBtn) { this.header.insert(new Element("a",{className:'close',href:"#"}).observe('click', this.close.bind(this))); }
		this.content = new Element('div',{className:'content'});
		
		if (this.options.src) {
			var iframeElmnt = new Element('iframe', {
				style: '',
				src: this.options.src,
				frameborder: 0,
				frameBorder: 0,
				marginwidth:0,
				marginheight:0,
				scrolling:'auto',
				width:'100%',
				height:this.options.height+'px'
			});
			iframeElmnt.identify();
			this.content.insert(iframeElmnt);
		} 

		if (this.options.img) {
			var imgElmnt = new Element('img', {
				className:'pointer',
				src: this.options.img,
				border: 0,
				alt:"",
				width:this.options.imgw || null,
				height:this.options.imgh || null,
				title:(unescape(this.options.imgtitle) || '')
			}).observe('click', this.close.bind(this));
			this.content.insert(imgElmnt);
			if (this.options.imgw) { this.options.width  = this.options.imgw; }
			if (this.options.imgh) { this.options.height = this.options.imgh; }
		}

		if (this.options.html) { this.content.insert(this.options.html); }
		else { if (this.options.content) { this.content.appendText(this.options.content || ' '); } }
		
		if (this.options.ajax) { var setAjax = new Ajax.Updater(this.content, this.options.ajax, {evalScripts:true, method:'get'}); }
		if (this.options.style) { this.content.setStyle(this.options.style); }
		this.element.insert(this.wrapperHead).insert(this.wrapperCnt.insert(this.header).insert(this.content)).insert(this.wrapperFoot).identify();
	},
  
	hide: function() {
		if (!this.visible) { return this; }
		this.element.hide(); //this.effect('hide'); --Could be an effect later on
		var pexec = new PeriodicalExecuter(function(executer) {
			if (this.element.visible()) { return; }
			this.visible = false;
			this.element.remove();
			executer.stop();
		}.bind(this), 0.1);
		return this;
	},

	// Adds window elements to the DOM
	addElements : function(elmnt) { this.windowManager.container.appendChild(elmnt); },
	createDiv : function (className, options) { return new Element('div', Object.extend({ className: className }, options)); },
	observe: function(eventName, handler) {
		this.element.observe('window:' + eventName, handler.bind(this));
		return this;
	},
	fire: function(eventName, memo) {
		memo = memo || { };
		memo.window = this;
		return this.element.fire('window:' + eventName, memo);
	}
});

document.observe("dom:loaded", function() { kUI.winMngr = new kUI.WindowManager(); });