jQuery.fn.simplefade = function(settings) {
	jQuery.simplefade(this, settings);
	return this;
};

jQuery.simplefade		= function (elemental, settings) {
	if(!(elemental instanceof jQuery))
		elemental = jQuery(elemental);

	var simplefade;
	
	elemental.data('simplefade', (simplefade = new jQuery.simplefade.init(elemental, settings)));
	return simplefade;
};
jQuery.simplefade.count = 0;

jQuery.simplefade.init = function(elemental, settings) {
	if(!(elemental instanceof jQuery))
			elemental = jQuery(elemental);
	
	s = this.settings;
	this.settings = jQuery.extend(true, {}, s, settings);
						
	this.list		= elemental.find('ul')
		.eq(0)
		.find('> li');

	this.elemental	= elemental;
	var n;
	this.index		= ((typeof(this.settings.index) != 'undefined' && !isNaN(n = new Number(this.settings.index)) && n > 0 && n <= this.list.length) ? n : 1);
	
	if(jQuery.isFunction(this.settings.initCallback))
		this.settings.initCallback.apply(null, [this]);
	
	this.elemental.css({
				'position'	: 'relative'
	});	
		
	this.list
		.css({
				'position'			: 'absolute'
				,'top'				: '0px'
				,'left'				: '0px'
				,'list-style-type'	: 'none'
		}).hide();


	this._animation('Before', 'In', 'init', true, 0);
	this.list.eq((this.index - 1))
			.show()
		.end(); 
	this._animation('After', 'In', 'init', true, 0);
	
	this.list._dofunction	= function(f) {
			f();	
			return this;
	};

	this.auto();
};

jQuery.simplefade.init.prototype = {
	'interval'		: null
	,'_windowhack'	: false
	,'settings'		: {
		'auto'			: 3.5
		, 'wrap'			: 'circular'
		, 'animation'   	: 'normal'
		, 'direction'		: 'ltr'
		, 'initCallback'	: null
		, 'itemVisibleInCallback'	: {
			  'onBeforeAnimation'	: null,
			  'onAfterAnimation'	: null
		}
		, 'itemVisibleOutCallback'	: {
			  'onBeforeAnimation'	: null,
			  'onAfterAnimation'	: null
		}
	}
	, 'index'		: 1
	, 'elemental'	: null	
	, 'list'		: null
	, 'moveLock'	: false
	, '_auto'		: null
	, 'auto'		: function(onoff) {
			/** try { console.debug("automatic next! ", this.elemental)}
			catch(e) { } /**/

		if(this.settings.auto) {
				
			
			if(typeof(onoff) !== 'undefined' && onoff !== null) {
				if(onoff) {
					this.auto(false);
					this.interval = setTimeout(this._auto, this.settings.auto * 1000);
					
				} else if(this.interval !== null) {
					clearInterval(this.interval);
					this.interval = null;				
				}
			} else {
				if(this.interval !== null) 
					this.auto(false)
					
				var self		= this;
				if(this._auto === null) {
					this._auto = function() {
						self._next();
						self.auto(true);
					};
				}			
				
				this.moveLock = false;
				this.auto(true);												
			} 
		}		
	}
	, '_animation'		: function(beforeafter, inout, type, manual) {
		var fs	= 'itemVisible'+inout+'Callback';
		var fn	= 'on'+beforeafter+'Animation';

		if(manual && ((beforeafter == 'After' && type == 'In') || type == null))
			this.auto();
		
		if(typeof(this.settings[fs]) != 'undefined' && jQuery.isFunction(this.settings[fs][fn])) {
			this.settings[fs][fn](this, this.list.eq((this.index - 1)), this.index, type);
		}
	}
	, 'move'		: function(index) {		
		if(!this.moveLock) {
			this.moveLock = true;

			if(this.index == index) {
				if(this.interval != null) 
					clearInterval(this.interval);

				this.auto();
			} else
				this._move(null, true, index);			
		}
	}
	, '_move'		: function(type, manual, to) {		
		if(!manual && this.index == this._getFadeInIndex(type)) return undefined;
		
		var self = this;

		if(manual && this.settings.auto && this.interval != null) 
				clearInterval(this.interval);
	
		this.list
				._dofunction(function(){
					self._animation('Before', 'Out', type, manual);
				})		
				.eq((this.index - 1))
					.fadeOut(this.settings.animation, function() {
						self._animation('After', 'Out', type, manual);						
					})
				.end();
		
		this.index = ((to) ? to : this._getFadeInIndex(type));
		this.list
				._dofunction(function(){
					self._animation('Before', 'In', type, manual);
				})
				.eq((this.index - 1))
					.fadeIn(this.settings.animation, function() {					
						self._animation('After', 'In', type, manual);
					});
	}	
	, 'prev'		: function() {
		this._prev(true);
	}
	, '_prev'		: function(manual) {
		this._move('prev', manual);
	}
	, 'next'		: function() {
		this._next(true);
	}
	, '_next'		: function(manual) {
		this._move('next', manual);
	}
	,'_getFadeInIndex' : function(move) {
		var inidx = 0 + this.index;
		
		if(move) {
			if(
				(move === 'next' && this.settings.direction === 'ltr') 
				|| (move === 'prev' && this.settings.direction === 'rtl')
			) {				
				if(++inidx > this.list.length)
					return 1;				 
			} else if(--inidx <= 0)
				return this.list.length;				
			
			return inidx;
		} else return 1;
	}
};

jQuery.simplefade.init.prototype.fade	= jQuery.simplefade.init.prototype.move;
jQuery.simplefade.init.prototype.scroll	= jQuery.simplefade.init.prototype.move;
