/**
 * @author alexander.farkas
 */
(function($){
	
var posExclude = {
	absolute: /absolute/,
	relative: /absolute|fixed|relative/
};
function addStyles(jElm, styles){
	var elem 	= jElm[0];
	if(!elem){return jElm;}
	var elemStyle = elem.style;
	if(styles.position && posExclude[styles.position].test($.curCSS(elem, 'position'))){
	styles = $.extend({}, styles);
	delete styles.position;
	}
	for(var style in styles){
	elemStyle[style] = styles[style];
	}
	return jElm;
}
$.fn.fadeOver = function(opts){
	if(!this[0]){return this;}
	opts = $.extend({}, $.fn.fadeOver.defaults, opts);
	if((this.length > 1 || opts.hideElement.length > 1)){
	console.log('fadeOver: wir können immer nur ein hideElement bzw. ein showElement behandeln');
	}
	
	var jElm 		= $(this[0]),
	parentElement 	= (opts.parentSel) ? jElm.closest(opts.parentSel) : jElm.parent(),
	animInCSS 	= {
				start: {
					position: 'absolute',
					top: (parseInt(parentElement.css('paddingTop'), 10) || 0),
					left: (parseInt(parentElement.css('paddingLeft'), 10) || 0),
					display: 'block'
				},
				end: {},
				after: {
					position: '', top: '', left: ''
				}
				},
	animOutCSS 	= $.extend(true, {}, animInCSS, {after: {}}),
	parentStartStyles = {
				position: 'relative',
				zoom: '1',
				overflow: 'hidden',
				height: parentElement.height() +'px'
				},
	parentEndStyles = {height: ''}
	;
	if(opts.stopAll){
	opts.hideElement.stop(true, true);
	jElm.stop(true, true);
	}
	if(opts.hideStyle === 'visibility'){
	animInCSS.start.visibility = '';
	animOutCSS.after.visibility = 'hidden';
	} else {
	animInCSS.start.display = 'block';
	animOutCSS.after.display = 'none';
	}
	
	opts.showElement = jElm;
	
	if (opts.inAnim) {
	$.each(opts.inAnim.split(','), function(i, anim){
		$.fn.fadeOver.presets[anim](jElm, animInCSS, opts);
	});
	}
	
	if(opts.outAnim){
	$.each(opts.outAnim.split(','), function(i, anim){
		$.fn.fadeOver.presets[anim](opts.hideElement, animOutCSS, opts);
	});
	}
	
		
	function animateParentHeight(){
	parentElement
		.animate(
		{height: jElm.outerHeight({margin: true})},
		$.extend({}, opts.animOpts, {
			complete: function(){
			parentElement.css(parentEndStyles);
			if(opts.animateHeight === 'linear'){
				opts.complete.apply(jElm[0]);
			}
			}
		})
		);
	}
	
	addStyles(parentElement, parentStartStyles);
	addStyles(opts.hideElement, animOutCSS.start);
	
	if(opts.outAnim){
	opts.hideElement.animate(animOutCSS.end, $.extend({}, opts.animOpts));
	}
	addStyles(jElm, animInCSS.start);
	if (opts.inAnim) {
	jElm.animate(animInCSS.end, $.extend({}, opts.animOpts, {
		complete: function(){
		if (opts.hideStyle === 'visibility') {
			opts.hideElement.parent().css({
			overflow: 'hidden',
			height: 0
			});
		}
		opts.hideElement.css(animOutCSS.after);
		jElm.css(animInCSS.after);
		if (!opts.animateHeight) {
			parentElement.css(parentEndStyles);
		}
		
		if (opts.animateHeight !== 'linear') {
			opts.complete.apply(this, arguments);
		}
		else {
			animateParentHeight();
		}
		}
	}));
	}
	if(opts.hideStyle === 'visibility'){
	jElm.parent().css('height', '');
	}
	
	if(opts.animateHeight === 'sync'){
	animateParentHeight();
	}
	return this;
};
$.fn.fadeOver.defaults = {
	animateHeight: false, // false | sync || linear
	inAnim: 'fadeIn',
	outAnim: 'fadeOut',
	hideStyle: 'display',
	parentSel: false,
	hideElement: $([]),
	stopAll: true,
	complete: $.noop,
	animOpts: {
	duration: 400
	}
};
$.fn.fadeOver.presets = {
	fadeIn: function(jElm, css, opts){
	if(!jElm[0]){return css;}
	if( jElm[0].offsetHeight < 3 || jElm[0].offsetWidth < 3 || jElm.css('visibility') === 'hidden' ){
		css.start.opacity = 0;
	}
	css.end.opacity = 1;
	css.after.opacity = '';
	return css;
	},
	fadeOut: function(jElm, css, opts){
	css.end.opacity = 0;
	return css;
	}
};
$.fn.crossFade = $.fn.fadeOver;
})(jQuery);
