Layer = Class.create();
Layer.prototype = {
		initialize: function(settings) {
			this._events = {};
			this.content = null;
			this.contentNode = null;
			this.settings = {
					fixed: true,
					layerClass: "layerclass",
					backgroundColor: "#000",
					zIndex: 99,
					opacity: 70,
					duration: 0.15
			};
			Object.extend(this.settings, settings);
			if(this.settings.content == null) {
				this.settings.content = new Element("div").update("You forgot to define a content for this layer.");
			}
			this.layer = new Element("div");

			// CSS
			this.layer.addClassName(this.settings.layerClass);
			this.layer.setStyle({
					position: "fixed",
					top: "0",
					left: "0",	
					height: "100%",		
					width: "100%",
					zIndex: this.settings.zIndex,
					background: this.settings.backgroundColor,
					display: "none"
			});
			document.body.appendChild(this.layer);
			Event.observe(this.layer, "click", this.close.bind(this));
		},
		
		observe: function(eventName, callback) {
			this.addEventListener(eventName, callback, false)
		},
		
		addEventListener: function(eventName, callback, bubble) {
			if(this._events[eventName] == null) {
				this._events[eventName] = new Array();
			}
			if(Object.isFunction(callback)) {
				this._events[eventName][this._events[eventName].length] = callback;
			}
		},
		
		dispatchEvent: function(event) {
			callbacks = this._events[event.eventName];
			if(callbacks != null) {
				callbacks.each(function(val, key) {
					memo = event.memo || {};
					val(memo);
				});
			}
		},
		
		fireEvent: function(eventName, event) {
			this.dispatchEvent(event);
		},
		
		reset: function(element) {
			if(element != null) {
				element.setStyle({
					display: "none"
				});
			}
		},

		open: function() {
			this.update(this.settings.content);
			this.reset(this.contentNode);
			this.reset(this.layer);
			
			Effect.Appear(this.layer, {duration: this.settings.duration, from:0, to:(this.settings.opacity / 100)});
			Effect.Appear(this.contentNode, {duration: this.settings.duration, from:0, to:(1)});
			Event.fire(this, "layer:open", {layerInstance: this});
		},
		
		close: function() {
			Effect.Fade(this.layer, {duration: this.settings.duration, from:(this.settings.opacity / 100), to: 0} );
			var self = this;
			Effect.Fade(this.contentNode, {duration: this.settings.duration, from:(1), to: 0, afterFinish: function(){
				self.contentNode.remove();
				self.contentNode = null;
			}});
			Event.fire(this, "layer:close", {layerInstance: this});
			this.reset(this.layer);
		},
		
		update: function(content) {
			if(content != null) {
				if(this.contentNode != null) {
					this.contentNode.remove();
				}
				if(Object.isString(content)) {
					this.content = content;
				} else {
					this.content = content.cloneNode(true);
				}
				this.contentNode = new Element("div").update(this.content);
				document.body.appendChild(this.contentNode);
				layerPosition = "fixed";
				layerTop = "50%";
				layerLeft = "50%";
				contentDimensions = this.contentNode.childElements()[0].getDimensions();
				layerMargin = "-" + (contentDimensions.height / 2) + "px 0px 0px -" + (contentDimensions.width / 2) + "px";
				if(!this.settings.fixed) {
					dimensions = document.viewport.getDimensions();
					offset = document.viewport.getScrollOffsets();
					layerPosition = "absolute";
					layerTop = (offset.top + (dimensions.height / 2)) + "px";
					layerLeft = (offset.left + (dimensions.width / 2)) + "px";
				}
				this.contentNode.setStyle({
					zIndex: (this.settings.zIndex + 1),
					position: layerPosition,
					top: layerTop,
					left: layerLeft,
					margin: layerMargin
				});
			}
		}
}
