/**
 * @author Stephan Wagner <steve.wagner@kigg.de>
 */

var tt_popUp = new Class({
	
	Implements: [Options,Events],
	
	options: {
		id: '',						// id of the popup table
		classes: '',				// classes added to the popup table
		target_id: '',				// id of element where the arrow should be shown
		www: '',
		width: 'auto',		
		height: 'auto',
		zIndex: '8000',
		content: '',
		title: '',					// adds a title to the popup
		positions: {
			x: 'center',			// if (y = bottom, top) { x can be left, center, right } elseif (y = right, left) { x can be top, center, bottom}
			y: 'bottom',			// can be bottom, top, right, left
			arrow: 'center' 		// arrow pointer position relative to target
		},
		positionsRelative: {
			target_id: '',			// positions the popup relative to the element with id = target_id
			target_side: 'left',	// can be left, right
			popup_side: 'left'		// can be left, right
									// target_side will have x coords of popup_side
		},
		offsets: {
			x: 0,					// offset popup x or -x px horizontal
			y: 0,					// offset popup y or -y px vertical
			arrow: 0				// offset the arrow x or -x px horizontal or vertical depending on positions.y
		},
		arrow: {
			show: true,				// show or hide arrow
			width: 22,				// arrow img width when positions.y = bottom or top
			height: 10				// arrow img height when positions.y = bottom or top
		},
		fadeDuration: 300,
		keys: { 
			esc: function() { this.close(); } 
		},
		closeOnClick: false,		// close this popup when clicking anywhere
		closeOnBodyClick: false,	// close this popup when clicking anywhere except the pupUp itself
		delayOpen: 0,				// delay opening the popup in ms
		
		addLoader: false,
		
		timer: $empty,
		tween: $empty
		
	},
	
	initialize: function(options) {
		this.setOptions(options);
		if (this.options.positions.y == 'right' || this.options.positions.y == 'left') {
			var arrow_dump = this.options.arrow.width;
			this.options.arrow.width = this.options.arrow.height;
			this.options.arrow.height = arrow_dump;
		}
		this.draw();
		this.listener();
	},
	listener: function() {
		
	},
	draw: function() {
		if ($(this.options.id) == null) {
			this.container = new Element('table',{
				'class': 'tt_popUp ' + this.options.classes,
				'id': this.options.id,
				styles: {
					'z-index': this.options.zIndex,
					opacity: 0
				}
			}).inject(document.body,'bottom');
			this.header = new Element('tr').inject(this.container);
			this.tl = new Element('td').addClass('tt_popUp_tl').inject(this.header);
			this.t = new Element('td').addClass('tt_popUp_t').inject(this.header);
			this.tr = new Element('td').addClass('tt_popUp_tr').inject(this.header);
			
			if(this.options.title != '') {
				this.header_title = new Element('tr').inject(this.container);
				this.l_title = new Element('td').addClass('tt_popUp_l_title').inject(this.header_title);
				this.t_title = new Element('td').addClass('tt_popUp_t_title').set('html', this.options.title).inject(this.header_title);
				this.r_title = new Element('td').addClass('tt_popUp_r_title').inject(this.header_title);
			}	
			this.content_container = new Element('tr').set('id', (this.options.id ? this.options.id + '_content_tr' : '')).inject(this.container);
			this.l = new Element('td').addClass('tt_popUp_l').inject(this.content_container);
			this.content = new Element('td').addClass('tt_popUp_content').set('id', (this.options.id ? this.options.id + '_content' : '')).setStyles({'width': this.options.width, 'height': this.options.height}).inject(this.content_container);
			
			this.injectContent();
			
			this.r = new Element('td').addClass('tt_popUp_r').inject(this.content_container);
			
			this.footer = new Element('tr').set('id', (this.options.id ? this.options.id + '_footer_tr' : '')).inject(this.container);
			this.bl = new Element('td').set('id', (this.options.id ? this.options.id + '_footer_bl' : '')).addClass('tt_popUp_bl').inject(this.footer);
			this.b = new Element('td').set('id', (this.options.id ? this.options.id + '_footer_b' : '')).addClass('tt_popUp_b').inject(this.footer);
			this.br = new Element('td').set('id', (this.options.id ? this.options.id + '_footer_br' : '')).addClass('tt_popUp_br').inject(this.footer);
			
			if(this.options.arrow.show) {
				switch(this.options.positions.y) {
					case 'top':
					var injectArrowTo = this.b;
					break;
					case 'bottom':
					var injectArrowTo = this.t;
					break;
					case 'left':
					var injectArrowTo = this.r;
					break;
					case 'right':
					var injectArrowTo = this.l;
					break;
				}
				this.arrow = new Element('img', { 'src': this.options.www + 'images/arrow_' + this.options.positions.y + '.png', 'width': this.options.arrow.width, 'height': this.options.arrow.height}).addClass('tt_popUp_arrow_' + this.options.positions.y).inject(injectArrowTo);
				
				if(!$(this.options.positionsRelative.target_id)) {
					switch(this.options.positions.arrow) {
						case 'left':
						case 'right':
						this.b.setStyles({'text-align': this.options.positions.arrow});
						this.t.setStyles({'text-align': this.options.positions.arrow});
						break;
						case 'top':
						case 'bottom':
						this.r.setStyles({'vertical-align': this.options.positions.arrow});
						this.l.setStyles({'vertical-align': this.options.positions.arrow});
						break;
						case 'center':
						default:
						switch(this.options.positions.y) {
							case 'left':
							case 'right':
							this.r.setStyles({'vertical-align': 'middle'});
							this.l.setStyles({'vertical-align': 'middle'});
							break;
							case 'top':
							case 'bottom':
							default:
							this.t.setStyles({'text-align': 'center'});
							this.b.setStyles({'text-align': 'center'});
						}
					}
					if(this.options.positions.arrow != 'center') {
						this.arrow.setStyle('margin-' + this.options.positions.arrow, this.options.offsets.arrow + 'px');
					}
				}
			}					
		} else {
			this.container 	= $(this.options.id);
			this.tl = this.container.getElement('.tt_popUp_tl');
			this.content = this.container.getElement('.tt_popUp_content');
			this.injectContent();
		}
		this.options.tween = new Fx.Tween(this.container, {
			duration: this.options.fadeDuration,
			link: 'cancel',
			property: 'opacity',
			onComplete: function(el) {
				if(el.getStyle('opacity') == 0) {
					el.setStyles({ top: -9000, left: -9000 });
					this.fireEvent('closeComplete');
				} else {
					this.fireEvent('openComplete');
				}
			}.bind(this)
		});
		return this;
	},
	injectContent: function() {
		if($(this.options.content) && $(this.options.content).get('html')) {
			try {
				$(this.options.content).inject(this.content, 'top').removeClass('hide');
			} catch (e) {
				//avoid errors on reload
			}			
		} else if($$('.' + this.options.content).length != 0) {
			$$('.' + this.options.content).inject(this.container.getElement('.tt_popUp_content'));
		} else {
			this.content.set('html', this.options.content);
		}
		
		if(this.options.addLoader) {
			new Element('div').set('id', this.options.id + '_loader').setStyles({'height': '30px'}).addClass('loader hide').inject(this.content);
		}
		
	},
	close: function(fast) {
		clearTimeout(this.options.timer);
		if(this.container.getStyle('opacity') != 0) {
			fast ? this.fireEvent('closeComplete') : '';
			this.fireEvent('close');
			this.options.tween[fast ? 'set' : 'start'](0);
			this._detachEvents();
		}
		return this;
	},
	
	open: function(fast, target, show_id, hide_classes) {
		clearTimeout(this.options.timer);
		var openPopUp = function() {
			this.fireEvent('open');
			fast ? this.fireEvent('openComplete') : '';
			
			if($(show_id) && $(show_id).hasClass(hide_classes ? hide_classes : this.options.content)) {
				$$('.' + (hide_classes ? hide_classes : this.options.content)).addClass('hide');
				$(show_id).removeClass('hide');
			}
			this.options.tween[fast ? 'set' : 'start'](1);
			this._attachEvents();
			this._position(target);
		}
		this.options.timer = openPopUp.delay(this.options.delayOpen, this);
		return this;
	},
	
	_attachEvents: function(target) {
		this.keyEvent = function(e){
			if(this.options.keys[e.key]) this.options.keys[e.key].call(this);
		}.bind(this);
		window.addEvent('keyup',this.keyEvent);
		
		this.resizeEvent = function() { this._position($(target) ? $(target) : (target ? target : this.options.target_id)); }.bind(this);
		window.addEvent('resize',this.resizeEvent);
		
		if(this.options.closeOnClick) {
			this.closeOnClick = function(el) { this.close(); }.bind(this);
			window.addEvent('mousedown', this.closeOnClick);
		}
		
		if(this.options.closeOnBodyClick) {
			this.closeOnBodyClick = function(el) { if(this.container && el.target != this.container && !this.container.hasChild(el.target)) { this.close(); } }.bind(this);
			window.addEvent('mousedown', this.closeOnBodyClick);
		}
			
		return this;
	},
	
	_detachEvents: function() {
		window.removeEvent('keyup', this.keyEvent);
		window.removeEvent('resize', this.resizeEvent);
		if(this.options.closeOnBodyClick) {
			document.removeEvent('mousedown', this.closeOnBodyClick);
		}
		if(this.options.closeOnClick) {
			document.removeEvent('mousedown', this.closeOnClick);
		}
		return this;
	},
	
	_position: function(target) {
		var coords = this.container.getCoordinates(),
			target_coords = ($(target) ? $(target) : (target ? target : $(this.options.target_id))).getCoordinates(),
			cellBorderWidth = this.tl.getStyle('width').toInt();
		
		if($(this.options.positionsRelative.target_id)) {
			var target_coords_rel = $(this.options.positionsRelative.target_id).getCoordinates();
			if(this.options.positionsRelative.popup_side == 'right') {
				var offsetWidth = -coords.width;
			}
			var posx = target_coords_rel.right + offsetWidth + this.options.offsets.x;
			
			var arrowMarginLeft = target_coords.left - posx - 9 - (this.options.arrow.width / 2) + (target_coords.width / 2);
			this.arrow.setStyle('margin-left', arrowMarginLeft + 'px');  // ToDo left right valign middle
		} else {
			switch (this.options.positions.arrow) {
				case 'left':
				var offsetToArrow = cellBorderWidth + (this.options.arrow.width / 2) + this.options.offsets.arrow;
				break;
				case 'right':
				var offsetToArrow = coords.width - (cellBorderWidth + (this.options.arrow.width / 2) + this.options.offsets.arrow);
				break;
				case 'top':
				var offsetToArrow = cellBorderWidth + (this.options.arrow.height / 2) + this.options.offsets.arrow;
				break;
				case 'bottom':
				var offsetToArrow = coords.height - (cellBorderWidth + (this.options.arrow.height / 2) + this.options.offsets.arrow);
				break;
				case 'center':
				default:
				if (this.options.positions.y == 'right' || this.options.positions.y == 'left') {
					var offsetToArrow = coords.height / 2;
				} else {
					var offsetToArrow = coords.width / 2;
				}
			}
			switch (this.options.positions.x) {
				case 'left':
				var posx = target_coords.left - offsetToArrow + this.options.offsets.x;
				break;
				case 'right':
				var posx = target_coords.right - offsetToArrow + this.options.offsets.x;
				break;
				case 'top':
				var posy = target_coords.top - offsetToArrow + this.options.offsets.x;
				break;
				case 'bottom':
				var posy = target_coords.bottom - offsetToArrow + this.options.offsets.x;
				break;
				case 'center':
				default:
				if (this.options.positions.y == 'right' || this.options.positions.y == 'left') {
					var posy = target_coords.top + (target_coords.height / 2) - offsetToArrow + this.options.offsets.x;
				} else {
					var posx = target_coords.left + (target_coords.width / 2) - offsetToArrow + this.options.offsets.x;
				}
			}
		}
		
		switch (this.options.positions.y) {
			case 'top':
			var posy = target_coords.top - coords.height - 2 - this.options.offsets.y;
			break;
			case 'left':
			var posx = target_coords.left - coords.width - 2 - this.options.offsets.y;
			break;
			case 'right':
			var posx = target_coords.right + 2 + this.options.offsets.y;
			break;
			case 'bottom':
			default:
			var posy = target_coords.bottom + 2 - this.options.offsets.y;
		}
		
		this.container.setStyles({'left': posx, 'top': posy});
		
		return this;
	},
	
	destroy: function() {
		this._detachEvents();
		this.container.dispose();
		delete this.container;
	},
});

//function closePopUps(classes, fast, except) {
//	$$(classes).each(function(el) { if(el.get('id') != except) { el[fast ? 'set' : 'tween']('opacity', 0); } });
//}

function openClosePopUp(popUp, fast, target) {
	popUp.container.getStyle('opacity') == 0 ? popUp.open(fast, target) : popUp.close(fast, target);
}

function changePopUpFooter(id, show) {
	var remove = show ? '' : 'error_';
	var add = show ? 'error_' : '';
	$(id + '_footer_bl').removeClass('tt_popUp_' + remove + 'bl').addClass('tt_popUp_' + add + 'bl');
	$(id + '_footer_b').removeClass('tt_popUp_' + remove + 'b').addClass('tt_popUp_' + add + 'b');
	$(id + '_footer_br').removeClass('tt_popUp_' + remove + 'br').addClass('tt_popUp_' + add + 'br');
}

function showHidePopUpError(id, show, fast) {
	var height = show ? '20px' : '0px';
	$(id + '_error_div')[fast ? 'setStyle' : 'tween']('height', height);
}

function errorPopUp(id, show, msg) {
	if(!$(id + '_error_div')) {
		var footer_error_tr = new Element('tr').inject(id + '_content_tr', 'after');
		var footer_error_td = new Element('td').inject(footer_error_tr).set('colspan', 3);
		var footer_error_div = new Element('div').addClass('tt_popUp_error_div').set('tween', { 'duration': 150 }).set('id', id + '_error_div').inject(footer_error_td);
		var footer_error_table = new Element('table').setStyles({'width': '100%'}).inject(footer_error_div);
		var footer_error_l = new Element('td').addClass('tt_popUp_error_l').inject(footer_error_table);
		var footer_error_content = new Element('td').addClass('tt_popUp_error_content').inject(footer_error_table);
		var footer_error_content_html = new Element('div').addClass('tt_popUp_error_content_html').set('id', id + '_error_content_html').inject(footer_error_content);
		var footer_error_r = new Element('td').addClass('tt_popUp_error_r').inject(footer_error_table);
	} else {
		showHidePopUpError(id, false, true);
	}
	
	if(show && msg) {
		$(id + '_error_content_html').set('html', msg);
		showHidePopUpError(id, true, false);
	}
	
	changePopUpFooter(id, show);
}

