var OverflowWrapper = new Class({
	Implements: [Events, Options],
	options : {
		'bgColor': 'none',
		'size'	 : 'normal',
		'position': 'auto'
	},
	initialize:function(html, options){
		this.setOptions(options);
		this.html = html;
		this.constructOverflow();
	},
	
	constructOverflow : function() {
		var shadow = new Element('div', {
			'class' : 'overflow_wrapper',
			'styles' : {
				'height' : this.getPageHeight().toString()+"px",
				'opacity': 0.7
			}
		}).inject($$('body')[0], 'top');
		
		if (this.options.bgColor != 'none')
			shadow.setStyle('background-color', this.options.bgColor);
		
		this.wrapper = new Element('div', {
			'class' : 'overflow_wrapper_container_'+this.options.size,
			'styles' : {
				'visibility' : 'hidden' 
			}
		});
		var wrapperContent = new Element('div', {
			'class' : 'overflow_wrapper_container_content_'+this.options.size
		}).inject(this.wrapper);
		var wrapperFoot = new Element('div', {
			'class' : 'overflow_wrapper_container_foot_'+this.options.size
		}).inject(this.wrapper, 'bottom');
		var closeContainer = new Element('span',{
			'class' : 'close_overflow_wrapper'
		}).inject(wrapperContent);
		var close = new Element('a',{
			'class' : 'close_overflow_wrapper'
		}).addEvent('click', function(e){
			this.destructOverflow();
			e.stop();
		}.bindWithEvent(this));
		close.inject(closeContainer);
		this.content = new Element('div',{
			'class' : 'content'
		}).inject(wrapperContent);
		
		if (typeof this.html == 'object')
			this.html.inject(this.content);
		else
			this.content.set('html', this.html);
		
		var relative = $$('body')[0];
		
		var morphShadow = new Fx.Morph(shadow, {
			'duration' : 'short',
			onComplete:function(){
				this.wrapper.inject(relative);
				if (this.options.position == 'absolute')
					this.positionWrapper('absolute');
				else
					this.positionWrapper();
				this.fireEvent('built');
				if (Browser.Engine.trident)
					var myFx = new Fx.Scroll(window).toElement($$('body')[0]);
			}.bind(this)
		});
		morphShadow.start({
			'opacity' : 0.5
		});
	},
	
	getPageHeight : function(){
		var D = document;
		return Math.max (
			Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
			Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
			Math.max(D.body.clientHeight, D.documentElement.clientHeight)
		);
	},
	
	positionWrapper : function(position){
		if (position == "absolute")
			this.wrapper.setStyles(this.getWrapperPosition(null, null, true));
		else
			this.wrapper.setStyles(this.getWrapperPosition());
		var morph = new Fx.Morph(this.wrapper,{
			onComplete: function(){
				this.fireEvent('show');
			}.bind(this)
		});
		morph.start({
			'visibility'	:	'visible'
		});
	},
	
	getWrapperPosition : function(forceY, forceX, abs){
		var lastP = null;
		
		var height = (forceY == null) ? this.wrapper.getSize().y : forceY;
		var width = (forceX == null) ? this.wrapper.getSize().x : forceX;
		
		var pageH = (Browser.Engine.trident) ? document.documentElement.clientHeight : window.innerHeight;
		var pageW = document.documentElement.clientWidth;
		
		var styles = {'top' : '0', 'position' : 'fixed', 'left' : '0'};
		if (height > pageH || abs == true) {
			styles.position = 'absolute';
			styles.top		= (Browser.Engine.trident) ? document.body.parentNode.scrollTop.toString()+"px" : window.scrollY.toString()+'px';
		}
		else 
			styles.top = ((pageH-height)/2).floor().toString()+"px";
		
		if (width > pageW)
			styles.position = 'absolute';
		else
			styles.left = ((pageW-width)/2).floor().toString()+"px";
		
		if (Browser.Engine.version == 4) {
			if (styles.position == 'fixed'){
				styles.position = 'absolute';
				styles.top = "0px";
			}
		}
		return styles;
	},
	
	destructOverflow : function(){
		var box = $$('body')[0].getFirst('div.overflow_wrapper');
		if (box != null){
			box.destroy();
			var shadow = $$('body')[0].getFirst('div.overflow_wrapper_container_'+this.options.size);
			if (shadow != null){
				var morphShadow = new Fx.Morph(shadow, {
					'duration' : 'short',
					onComplete:function(){
						shadow.destroy();
					}
				});
				morphShadow.start({
					'opacity' : 0
				});
			}
		}
	},
	
	replace : function() {
		var styles = this.getWrapperPosition();
		if (styles.top != this.wrapper.getStyle('top') || styles.left != this.wrapper.getStyle('left') || styles.position != this.wrapper.getStyle('position')){
			if (styles.position == 'absolute' && this.wrapper.getStyle('position') == "fixed"){
				var morph = new Fx.Morph(this.wrapper,{
					onComplete:function(){
						this.wrapper.setStyles({
							'position'  : 'absolute',
							'top'		: styles.top
						});
					}.bind(this)
				});
				morph.start({'top' : '0px'});
			}
			else if (styles.position == 'fixed' && this.wrapper.getStyle('position') == "absolute"){
				var morph = new Fx.Morph(this.wrapper, {
					onComplete:function(){
						this.wrapper.setStyles({
							'position'  : 'fixed',
							'top'		: styles.top
						});
					}.bind(this)
				});
				var top = (Browser.Engine.trident) ? (parseInt(styles.top.split("px")[0])+parseInt(document.body.parentNode.scrollTop)).toString()+"px" : (parseInt(styles.top.split("px")[0])+parseInt(window.scrollY)).toString()+"px";
				morph.start({
					'top' : top
				});
			}
			else {
				var morph = new Fx.Morph(this.wrapper);
				morph.start(styles);
			}
		}
	},
	
	set : function(html) {
		if (typeof html == 'object'){
			this.content.empty();
			html.inject(this.content);
		}
		else
			this.content.set('html', html);
	}
});

