/**
 * Roar - Notifications
 * Adaptations for Gyas by H.C. Hermsen <webdesign [at] hhermsen.nl>
 *  
 * Inspired by Growl
 *
 * @version		1.0.1
 *
 * @license		MIT-style license
 * @author		Harald Kirschner <mail [at] digitarald.de>
 * @copyright	Author
 */

var Roar = new Class({

	Implements: [Options, Events, Chain],

	options: {
		duration: 8000,
		position: 'lowerLeft',
		container: null,
		itemFx: null,
		width: 300,
		margin: {x: 10, y: 10},
		offset: 10,
		className: 'roar',
		onShow: $empty,
		onHide: $empty
	},

	initialize: function(options) {
		this.setOptions(options);
		this.items = [];
		this.container = $(this.options.container) || document;
	},

	alert: function(title, message, options) {
		var params = Array.link(arguments, {title: String.type, message: String.type, options: Object.type});
		var title = new Element('h2', {'html': $pick(params.title, '')});
		if (options && options.icon) title.grab(new Element('img', {'src': 'http://www.gyas.nl/visuals/gyas/cognac/icon/' + options.icon}), 'top');
		var items = [title];
		if (params.message) items.push(new Element('p', {'html': params.message}));
		return this.inject(items, options.link, params.options);
	},

	inject: function(elements, link, options) {
		if (!this.body) this.render();
		options = options || {};

		var offset = [-this.options.offset, this.options.margin.y];
		var column = 1;
		var last = this.items.getLast();
		if (last) {
			offset[0] = last.retrieve('roar:offset');
			offset[1] = offset[0] + last.offsetHeight + this.options.offset;
			column = last.retrieve('roar:column');
		}
		var x_offset = column * this.options.margin.x + (column - 1) * this.options.width;
		var to = {'opacity': 1};
		to[this.align.y] = offset;

		var item = new Element('a', {
			'href': link,
			'class': this.options.className,
			'opacity': 0,
			'onclick': (link ? "if(($(document).location.pathname + $(document).location.search) == '" + (link.split("#"))[0] + "') { if(confirm('De pagina wordt hiermee vernieuwd. Eventueel ingevulde informatie zal worden gewist.')) {  $(document).location = '" + link + "'; $(document).location.reload(true); } return false; }" : "") // single-/double-quotes niet omdraaien
		}).adopt(
			new Element('div', {
				'class': 'roar-bg',
				'opacity': 0.7
			}),
			elements
		);

		item.addEvents(
			{
				'mouseover': function(){this.getFirst().setStyle('opacity', 0.8)},
				'mouseout':  function(){this.getFirst().setStyle('opacity', 0.7)}
			});

		item.setStyle(this.align.x, x_offset).store('roar:offset', offset[1]).store('roar:column', column).set('morph', $merge({
			unit: 'px',
			link: 'cancel',
			onStart: Chain.prototype.clearChain,
			transition: Fx.Transitions.Back.easeOut
		}, this.options.itemFx));

		var remove = this.remove.create({
			bind: this,
			arguments: [item],
			delay: 10
		});

		var cross = new Element('a', {'class': 'close'});
		cross.addEvent('click', function(e){e.stop();remove.run();});
		cross.inject(item);

		this.items.push(item);

		if (this.options.duration && !options.sticky && !($defined(link) && ($(document).location.pathname + $(document).location.search) == (link.split('#'))[0])) {
			var over = false;
			var trigger = (function() {
				if (!over) remove();
			}).delay(this.options.duration);
			item.addEvents({
				mouseover: function() {
					over = true;
				},
				mouseout: function() {
					over = false;
					$clear(trigger);
					trigger = (function() {
						if (!over) remove();
					}).delay(this.options.duration)
				}.bind(this)
			});
		}
		item.inject(this.body);

		var windowHeight = window.getHeight();
		if(offset[1] + item.offsetHeight > windowHeight) {
			column += 1;
			item.setStyle(this.align.x, column * this.options.margin.x + (column - 1) * item.offsetWidth);
			offset = [-this.options.offset, this.options.margin.y];
			to[this.align.y] = offset;
			item.store('roar:offset', offset[1]).store('roar:column', column);
		}
				
		item.morph(to);
		
		return this.fireEvent('onShow', [item, this.items.length]);
	},

	remove: function(item) {
		var index = this.items.indexOf(item);
		if (index == -1) return this;
		this.items.splice(index, 1);
		item.removeEvents();
		var to = {opacity: 0};
		to[this.align.y] = item.getStyle(this.align.y).toInt() - item.offsetHeight - this.options.offset;
		var column_remove = item.retrieve('roar:column');
		item.morph(to).get('morph').chain(item.destroy.bind(item));

		var last;
		var windowHeight = window.getHeight();
		this.items.each(function(item, index, items) {
			var myFx = new Fx.Morph(item, {link: 'chain'});
			if(last) {
				var offset = last.retrieve('roar:offset') + last.offsetHeight + this.options.offset;
				if(last.retrieve('roar:column') == item.retrieve('roar:column')) {
					if(offset != item.retrieve('roar:offset')) {
						item.store('roar:offset', offset);
						myFx.start({'bottom': offset});
					}
				} else {
					if(offset + item.offsetHeight < windowHeight) {
						column = item.retrieve('roar:column');
						column -= 1;
						item.store('roar:column', column).store('roar:offset', offset);
						myFx.start({'left': column * this.options.offset + (column - 1) * item.offsetWidth, 'bottom': offset});
					} else {
						if(this.options.offset != item.retrieve('roar:offset')) {
							item.store('roar:offset', this.options.offset);
							myFx.start({'bottom': this.options.offset});
						}
					}
				}
			} else {
				if(this.options.offset != item.retrieve('roar:offset')) {
					item.store('roar:offset', this.options.offset);
					myFx.start({'bottom': this.options.offset});
				}
			}
			last = item;
		}, this);

		return this.fireEvent('onHide', [item, this.items.length]).callChain(item);
	},

	empty: function() {
		while (this.items.length) this.remove(this.items[0]);
		return this;
	},

	render: function() {
		this.position = this.options.position;
		if ($type(this.position) == 'string') {
			var position = {x: 'center', y: 'center'};
			this.align = {x: 'left', y: 'top'};
			if ((/left|west/i).test(this.position)) position.x = 'left';
			else if ((/right|east/i).test(this.position)) this.align.x = position.x = 'right';
			if ((/upper|top|north/i).test(this.position)) position.y = 'top';
			else if ((/bottom|lower|south/i).test(this.position)) this.align.y = position.y = 'bottom';
			this.position = position;
		}
		this.body = new Element('div', {'class': 'roar-body'}).inject(document.body, 'top');
		if (Browser.Engine.trident4) this.body.addClass('roar-body-ugly');
	}

});