(function(){

var instance = null;

var FlashMessage = this.FlashMessage = new Class({
	
	Implements: [Options, Events],
	
	options: {
		dflt: 'notice',
		insertion: {'element': 'main-content', 'where': 'top'},
		delay: 750,
		animate: true,
		build: true,
		useHtml: false
	},

	initialize: function(element, options){
		this.element = document.id(element) || new Element('div', {'id': element});
		if (instance) return instance;
		instance = this;
		this.setOptions(options);
		if (this.options.build) this._build();
	},
	
	_build: function(){
		var el = document.id(this.options.insertion.element) || document.id('subnav') || document.id('header');
		var where = this.options.insertion.where;
		this.element.inject(el, where);
		this.options.animate ? this.element.get('slide').hide() : this.element.hide();
		this.dflt = this[this.options.dflt];
	}.protect(),

	notify: function(){
		if (!this.caller) return this.dflt.apply(this, arguments);
		if (arguments.length < 1) {
			throw new Error("Function FlashMessage.notify called with " + arguments.length + " arguments, but expected at least 1.");
		}
		if ($type(arguments[0]) == 'element') {
			var message = arguments[0];
		} else {
			var message = (!this.options.useHtml) ? document.newTextNode(arguments[0]) : new Element('div', {'html': arguments[0]});
		}
		var buttons = [];
		for (var i = 1; i < arguments.length; i++) {
			var params = Array.link(arguments[i], {text: String.type, href: String.type});
			$extend(params, {'class': 'button', html: '<span><span>' + params.text + '</span></span>', styles: {'float': 'right'}});
			delete params.text;
			buttons.push(new Element('a', params));
		}
		this.element.empty();
		this.element.adopt(message, buttons);
		this.show();
	},
	
	clear: function(){
		this.element.empty();
		this.hide();
	},
	
	show: function(){
		if (this.options.animate) {
			var slide = this.element.get('slide');
			slide.slideIn.delay(this.options.delay, slide);
		} else {
			this.element.show();
		}
	},
	
	hide: function(){
		if (this.options.animate) {
			var slide = this.element.get('slide');
			slide.slideOut.delay(this.options.delay, slide);
		} else {
			this.element.hide();
		}
	}
	
});

var methods = {};
['notice', 'warning', 'error', 'success'].each(function(method){
	methods[method] = function(){
		this.element.className = method;
		return this.notify.apply(this, arguments);
	};
});

FlashMessage.implement(methods);

})();