var Slide = new Class({
		
		Extends: Fx.Tween,
		
		placeholder: 	$empty,
		absoluteStyles: $empty,
		size:	 		$empty,
		currentState: 	'in',
		
		initialize: function(element, options) {
			
			this.parent(element, options);
			this.createWrap(element);
			
		},
		
		createWrap: function(element) {
			
			var parentElement = element.getParent();
			
			while(parentElement.getStyle('position') == 'static' && parentElement != document.body)
				parentElement = parentElement.getParent();
			
			var wrapperDiv = new Element('div');
			
			var coordinates = element.getCoordinates(parentElement);
			
			var size = element.getSize();
			this.size = size;
			
			var wrapperPosition = 'absolute';
			if(element.getStyle('position') != 'absolute') wrapperPosition = 'relative';
			
			wrapperDiv.setStyles({
				'overflow': 'hidden', 
				'position': wrapperPosition,
				'width':	size.x,
				'height':	size.y,
				'float':	element.getStyle('float')
			});
			wrapperDiv.setStyles(element.getStyles("padding"));
			
			
			this.absoluteStyles = {
				'right':	parentElement.getSize().x - coordinates.right - parentElement.getStyle('border-right-width').toInt() + 'px',
				'bottom':	parentElement.getSize().y - coordinates.bottom - parentElement.getStyle('border-bottom-width').toInt() + 'px',
				'left':		coordinates.left - parentElement.getStyle('border-left-width').toInt() + 'px',
				'top':		coordinates.top - parentElement.getStyle('border-top-width').toInt() + 'px'
			};
			
			if(wrapperPosition == 'absolute') wrapperDiv.setStyles(this.absoluteStyles);
			
			element.setStyles({
				'position': 'absolute',
				'left':		0,
				'top':		0,
				'width':	size.x.toInt() - element.getStyle("padding-right").toInt() - element.getStyle("padding-left").toInt() - element.getStyle('border-top-width').toInt() - element.getStyle('border-bottom-width').toInt()+ 'px',
				'height':	size.y.toInt() - element.getStyle("padding-top").toInt() - element.getStyle("padding-bottom").toInt() - element.getStyle('border-left-width').toInt() - element.getStyle('border-right-width').toInt()+ 'px',
				'margin':	0,
				'z-index': 	element.getStyle("z-index")
				
			});
			
			wrapperDiv.wraps(element);
			this.element = wrapperDiv;
		},
		
		start: function(property, start, stop, targetState) {
			this.parent(property, start, stop);
			this.currentState = targetState;
		},
		
		slideTopIn: function() {
			return {
				property: 		'height', 
				from:			0, 
				to:				this.size.y, 
				targetState:	'in'
			};
		},
		
		slideBottomIn: function() {
			return {
				property: 		'height', 
				from:			0, 
				to:				this.size.y, 
				targetState:	'in'
			};
		},
		
		slideLeftIn: function() {
			return {
				property: 		'width', 
				from:			0, 
				to:				this.size.x, 
				targetState:	'in'
			};
		},
		
		slideRightIn: function() {
			return {
				property: 		'width', 
				from:			0, 
				to:				this.size.x, 
				targetState:	'in'
			};
		},
		
		slideTopOut: function() {
			return {
				property: 		'height', 
				from:			this.size.y, 
				to:				0, 
				targetState:	'out'
			};
		},
		
		slideBottomOut: function() {
			return {
				property: 		'height', 
				from:			this.size.y, 	
				to:				0, 
				targetState:	'out'
			};
		},
		
		slideLeftOut: function() {
			return {
				property: 		'width', 
				from:			this.size.x, 
				to:				0, 
				targetState:	'out'
			};
		},
		
		slideRightOut: function() {
			return {
				property: 		'width', 
				from:			this.size.x, 
				to:				0, 
				targetState:	'out'
			};
		},
		
		slide: function(mode, how, options) {
			
			if(how == this.currentState)
				return null;

			this.setOptions(options);
			
			how = how || 'toggle';
			mode = mode || 'top';
		
			
		
			switch(mode)
			{
				case 'right': this.creaPlaceHolder(); this.element.setStyle('position', 'absolute'); this.element.setStyles(this.absoluteStyles); this.element.setStyle('left', 'auto'); break;
				case 'bottom': this.creaPlaceHolder(); this.element.setStyle('position', 'absolute'); this.element.setStyles(this.absoluteStyles); this.element.setStyle('top', 'auto'); break;
			}
		
			var modeIn 	= this['slide' + mode.capitalize() + 'In']();
			var modeOut = this['slide' + mode.capitalize() + 'Out'](); 
		
			toggleMode = modeIn;
			if(this.currentState == 'in')
				toggleMode = modeOut;
				
			
			switch(how) {
				case 'show': 	this.set(modeIn.property, modeOut.from); this.currentState = 'in'; break;
				case 'hide': 	this.set(modeOut.property, modeOut.to); this.currentState = 'out'; break;
				case 'in':		this.start(modeIn.property, modeIn.from, modeIn.to, modeIn.targetState); break;
				case 'out':		this.start(modeOut.property, modeOut.from, modeOut.to, modeOut.targetState); break;
				case 'toggle':	this.start(toggleMode.property, toggleMode.from, toggleMode.to, toggleMode.targetState); break;	
			};
			
		},
		
		creaPlaceHolder: function() {
			if(!this.placeHolder)
			{
				this.placeHolder = this.element.clone(false);
				this.placeHolder.injectBefore(this.element);
			}
		},
		
		slideTop: function(how, options) {
			this.slide('top', how, options);
		},
		
		slideBottom: function(how, options) {
			this.slide('bottom', how, options);
		},
		
		slideLeft: function(how, options) {
			this.slide('left', how, options);
		},
		
		slideRight: function(how, options) {
			this.slide('right', how, options);
		}
		
	});
	
	Element.implement({
		
		slideEffect: $empty,
	
		slide: function(mode, how, options) {
		
			mode = mode || 'top';
		
			if(this.slideEffect == $empty)
				this.slideEffect = new Slide(this, options);
				
			this.slideEffect.slide(mode, how, options);
		},
		
		slideTop: function(how, options) {
			this.slide('top', how, options);
		},
		
		slideBottom: function(how, options) {
			this.slide('bottom', how, options);
		},
		
		slideLeft: function(how, options) {
			this.slide('left', how, options);
		},
		
		slideRight: function(how, options) {
			this.slide('right', how, options);
		}
	});
