//Yamoodow 1.0 - (c) 2009 Christian Opitz, Netzelf - http://netzelf.de - Released under the MIT License
var yamoodow = new Class({
	Implements: [Options,Events],
	options: {
		opener:null,
		title:'',
		buildTabs:true,
		width: 500,
		height: 400,
		verticalGap: 20,
		overlayOpacity: 0.6,
		template: 
			'<div id="{cssPrefix}Head" class="{cssPrefix}RightCorner">'+
				'<div class="{cssPrefix}LeftCorner">'+
					'<div id="{cssPrefix}Title"></div>'+
					'<div id="{cssPrefix}CloseHandle"></div>'+
				'</div>'+
			'</div>'+
			'{tabs}'+
			'{content}'+
			'<div id="{cssPrefix}Bottom">'+
				'<div class="{cssPrefix}RightCorner">'+
					'<div class="{cssPrefix}LeftCorner">'+
						'<div id="{cssPrefix}StatusBar"></div>'+
					'</div>'+
				'</div>'+
			'</div>',
		selectors: {
			closeHandle: '#{cssPrefix}CloseHandle',
			title: '#{cssPrefix}Title',
			statusText: '#{cssPrefix}StatusBar',
			loading: '#{cssPrefix}StatusBar'
		},
		overlayTweenOptions: {
			duration: 300
		},
		windowTweenOptions: {
			duration: 300
		},
		lang: {
	  		loading: 'Loading...',
	  		loaded: 'Ready',
	  		failure: 'Error: ',
	  		httpCodes: {
		        '404':'page not found',
		        '403':'forbidden'
			}
		},
		cssPrefix: 'ymd',
		cache: true,
		placeholders: {}
	},
	initialize: function(tabs, options) {
		this.setOptions(options);
		this.tabs = tabs;
		
		this.overlay = new Element('div', {id: this.options.cssPrefix+'Overlay', events: {click: this.closeWin.bind(this)}});
		this.win = new Element('div', {id: this.options.cssPrefix+'Window', styles: {width: this.options.width}});
		this.overlay.set('tween', this.options.overlayTweenOptions).fade('hide');
		this.win.set('tween', this.options.windowTweenOptions).fade('hide');
				
		window.addEvent('domready',function(){
			$(document.body).adopt(this.overlay, this.win);
			
			var replace = new Hash(this.options);
			replace.extend(this.options.placeholders);
			replace.content = '<div id="'+this.options.cssPrefix+'ContainerWrap"></div>';
			if (this.tabs && this.options.buildTabs) {
				replace.tabs = '<div id="'+this.options.cssPrefix+'Navi'+'"></div>';
			}
			
			this.win.set('html', this.options.template.substitute(replace));
			
			if (this.tabs && this.options.buildTabs) {
				//Build Navi
				this.nav = new Element('ul',{styles:{'margin':0,'padding':0}}).inject(this.getElement('#'+this.options.cssPrefix+'Navi'));
				this.tabs.each(function(tab,i){
					this.tabs[i].li = new Element('li', {
						'text':tab.text,
						'events': { 
							'click': this.load.bind(this,i)
					}}).inject(this.nav)
				}.bind(this));
			}
			
			this.title = this.getElement(this.options.selectors.title.substitute(replace));
			this.title.set('text', this.options.title);
			this.closeHandle = this.getElement(this.options.selectors.closeHandle.substitute(replace));
			this.closeHandle.addEvent('click', this.closeWin.bind(this));
			this.statusText = this.getElement(this.options.selectors.statusText.substitute(replace));
			this.loadingEl = this.getElement(this.options.selectors.loading.substitute(replace));
			
			this.windowPadding = this.win.getSize().y;
			if (this.options.height == 'auto') {
				this.addEvent('success', this.resizeWin.bindWithEvent(this));
				this.height = this.windowPadding;
			}else{
				this.height = this.options.height;
			}
			
			this.containerWrap = this.getElement('#'+this.options.cssPrefix+'ContainerWrap').setStyles({'overflow':'auto', 'height':this.height - this.windowPadding});
			this.container = new Element('div', {'class': this.options.cssPrefix+'Content'}).inject(this.containerWrap);
			
			if (this.options.opener) {
				this.options.opener.removeEvent('click');
				this.options.opener.removeProperty('href');
				this.options.opener.addEvent('click', this.openWin.bind(this));
			}
		}.bind(this));
		
		this.active = -1;
		this.cache = [];
		this.resizeWin();
		
		return this;
	},
	getElement: function(selector) {
		var el = this.win.getElement(selector);
		return (el != null) ? el : new Element('div');
	},
	openWin: function() {
		this.overlaySetup(1);
		
		this.overlay.fade(this.options.overlayOpacity);
		this.win.fade('in');
		
		if (this.active == -1 || $type(arguments[0]) == 'number') {
			var tab = ($type(arguments[0]) == 'number') ? arguments[0] : 0;
			this.active = tab;
			this.load(tab);
		}
	},
	resizeWin: function()
	{
		this.windowScroll = window.getScroll();
		this.windowSize = window.getSize();
		if (this.options.height == 'auto')
		{
			var	cH = this.container.getSize().y,
				newSize = cH + (2 * this.options.verticalGap) + this.windowPadding;
			if (newSize <= this.windowSize.y) {
				this.height = cH + this.windowPadding;
			}else{
				this.height = this.windowSize.y - (2 * this.options.verticalGap);
				cH = this.windowSize.y - newSize + cH;
			}
			this.position();
			this.containerWrap.setStyle('height',cH);
		}else{
			this.position();
		}
	},
	closeWin: function() {
		this.overlay.fade('out');
		this.win.fade('out');
		this.overlaySetup(0);
	},
	position: function()
	{
		compatibleOverlay = Browser.Engine.trident4 || (this.overlay.currentStyle && (this.overlay.currentStyle.position != "fixed"));
		if (compatibleOverlay) {
			this.overlay.style.position = "absolute";
		}
		this.win.setStyles({"left": this.windowScroll.x + (this.windowSize.x / 2) - (this.options.width / 2),'top': this.windowScroll.y + (this.windowSize.y / 2) - (this.height / 2)});
		if (compatibleOverlay) this.overlay.setStyles({left: this.windowScroll.x, top: this.windowScroll.y, width: this.windowSize.x, height: this.windowSize.y});
	},
	overlaySetup: function(open)
	{
		var fn = open ? "addEvent" : "removeEvent";
		window[fn]("scroll", this.resizeWin.bind(this))[fn]("resize", this.resizeWin.bind(this));
	},
	/* if second argument is set to true, cache of this tab is emptyed and tab gets reloaded */
	load: function(i)
	{
		if (this.options.buildTabs) {
			this.tabs[this.active].li.removeClass(this.options.cssPrefix+'Active');
			this.tabs[i].li.addClass(this.options.cssPrefix+'Active');
		}else if(this.tabs[this.active].title) {
			this.title.set('text', this.tabs[this.active].title);
		}
		this.toCache = this.active;
		this.active = i;
		if (!arguments[1]) {
			if (this.getCache()) return;
		} else this.cacheClear(this.active);
		this.tabs[this.active].status = null;
		if (this.tabs[i].iframe) this.loadIframe(); else this.loadAjax();
	},
	/* arguments:
	None (clear Statusbar immediately) or Text(optional), Add loading class (optional, bool), delay till message disappears (optional), Event (optional) */
	triggerStatus: function() {
		this.statusText.set('html',arguments[0] || '');
		$clear(this.statusTimer);
		if (arguments[1]) this.loadingEl.addClass(this.options.cssPrefix+'Loading'); else this.loadingEl.removeClass(this.options.cssPrefix+'Loading');
		if (arguments[2]) this.statusTimer = this.triggerStatus.delay(arguments[2]*1000,this);
		if (arguments[3]) this.fireEvent(arguments[3],[$merge({container:this.container},this.tabs[this.active]),this.active]);
	},
	loadIframe: function(){
		this.triggerStatus(this.options.lang.loading,1,0,'load');
		this.writeCache();
		this.container.setStyle('overflow','visible');
		this.iframe = new IFrame({
			src: this.tabs[this.active].url,
			styles: {
				width:this.options.width,
				height:this.contentHeight,
				border:'none'
			},
			events: { load: this.triggerStatus.bind(this,[this.options.lang.loaded,0,3,'success']) }
		}).inject(this.container.empty());
	},
	loadAjax: function(){
		this.triggerStatus(this.options.lang.loading,1,0,'load');
		this.writeCache();
		this.container.setStyle('overflow','auto');  
		new Request.HTML({
			url:this.tabs[this.active].url,
			update:	this.container,
			onSuccess: this.triggerStatus.bind(this,[this.options.lang.loaded,0,3,'success']),
			onFailure: function(xhr){
				this.tabs[this.active].status = xhr.status;
				this.triggerStatus(this.options.lang.failure+this.options.lang.httpCodes[xhr.status],0,0,'failure'); }.bind(this)
		}).get();
	},
	writeCache: function() {
		if (!this.options.cache) return;
		this.cache[this.toCache] = this.container.setStyle('display','none');
		this.container = new Element('div', {'class': this.options.cssPrefix+'Content',styles:{overflow:'auto',height:'100%'}}).inject(this.containerWrap);
	},
	getCache: function() {
		if (!this.options.cache || !this.cache[this.active]) return false;
		this.cache[this.toCache] = this.container.setStyle('display','none');
		this.container = this.cache[this.active].setStyle('display','');
		return true;
	},
	cacheClear: function(i) {
		if (!this.options.cache) return;
		if (this.cache[this.active]) {
			this.cache[this.active].destroy();
			this.cache[this.active] = 0;
		}
	}
});
