/**
 * FotoSlider is a custom-built class (using jQuery) that aims to create transition-effects for images.
 * 
 * Efects available:
 * - crossFade (vertical)
 */
var FotoSlider = {
	instances	: [],
	
	/**
	 * defaults can be over-ridden in FotoSlider.init(config [Obj])
	 */
	defaults 	: {
		/**
		 * default jQuery-selector to apply FotoSlider to
		 */
		selector 	: '.fotoslider',
		/**
		 * default speed for this FotoSlider-instance
		 */
		speed 		: 750,
		/**
		 * autoplay + interval
		 */
		autoplay 	: true,
		autoplayInt : 5000,
		/**
		 * default effect for this FotoSlider-instance
		 */
		effect 		: 'flat'
	}, 
	
	/**
	 * Initialize a configured FotoSlider using config [Obj] to parse configuration overriding this.defaults
	 */
	init		: function(config){
/*
		this.images = $(this.selector + ' img');
		for(var n in this.images){
			var imgsrc = new Image(this.images[n].src);
			this.sources.push(imgsrc)
		}
*/
		config = this.sanitizeConfig(config);
		$(config.selector).each(function(idx, el){
			FotoSlider.createInstance(el, config);
		});
	},
	
	/**
	 * inspect config for usability and revert invalid input to defaults
	 */
	sanitizeConfig 	: function(config){
		if(!config) return this.defaults;
		// selector
		if(!config.selector) config.selector = this.defaults.selector;
		// speed
		if(!config.speed || config.speed < 100) config.speed = this.defaults.speed;
		// autoplay
		config.autoplay = (config.autoplay == undefined) ? this.defaults.autoplay : Boolean(config.autoplay);
		config.autoplayInt = (config.autoplayInt == undefined || config.autoplayInt <= 0) ? this.defaults.autoplayInt : parseInt(config.autoplayInt);
		// effect
		if(!config.effect || !this['_proto_'+config.effect]) config.effect = this.defaults.effect;
		return config;
	},
	
	createInstance 	: function(el, config){
		var instance 		= $(el);
		if(!instance.hasClass('__fotoslidered__')){
			instance.addClass('__fotoslidered__');
			instance.autoplay 		= config.autoplay;
			instance.autoplayInt 	= config.autoplayInt;
			instance.fotoslider = true;
			instance.timeoutId 	= 0;
			instance.config 	= config; // administrative ... for debug
			instance.nextIndex 	= -1;
			instance.speed 		= config.speed;
			instance.items 		= [];
			instance.controls 	= instance.find('.controls')[0];
			// we don't use controls yet
			$(instance.controls).hide();
			
			this['_proto_'+config.effect](instance);
			
			this.instances.push(instance);
			
			if(instance.autoplay){
				FotoSlider.autoNext(instance._index);
			}
				
		}else{
			//alert('element [class="'+el.className+'"] is already fotoslidered');
		}
		
		return instance;
	},
	
	/**
	 * slide FotoSlider instance using the effect that was parsed on initialization
	 */
	slide 		: function(instIdx, itemIdx){
		var instance 		= this.instances[instIdx];
		instance.nextIndex 	= itemIdx;
		var activeItem 		= $(instance.find('.item.active')[0]);
		activeItem.trigger('click');
	},
	
	/**
	 * the simplest plugin ... default
	 */
	_proto_flat 		: function(instance){
		instance._index = this.instances.length;
		instance.find('.item').each(function(idx, el){
			var item 		= $(this);
			item.bind('click', function(evt){
				var offItem = item;
				var onIndex = (instance.nextIndex >= 0) ? instance.nextIndex : ((idx+1)%(instance.items.length));
				var onItem 	= $(instance.items[onIndex]);
				offItem.hide();
				onItem.show();
			}).hide();
			instance.items.push(item);
		});

		$(instance.items[instance.items.length-1])
			.addClass('active')
			.trigger('click');
			
	},
	
	/**
	 * plug-in new effects
	 */
	plugin 		: function(effectName, func){
		this['_proto_'+effectName] = func; 
	},
	fakeMouseLeave 			: function(instIdx, itemIdx){
		$(this.instances[instIdx].items[itemIdx]).trigger('mouseleave');
	},
	autoNext 			: function(instIdx){
		var instance = this.instances[instIdx];
		if(instance.timeoutId){
			if(!instance.postponed){
				$(instance.find('.item.active')[0]).trigger('click');
			}
			clearTimeout(instance.timeoutId);
		}
		if(instance.postponed){
			instance.postponed = false;
		}
		instance.timeoutId = setTimeout('FotoSlider.autoNext('+instIdx+')', instance.autoplayInt);
	},
	postpone 				: function(instIdx){
		var instance = this.instances[instIdx];
		instance.postponed = true;
	}
};


// plug-in crossFade effect

/**
 * a more complicated pseudo-prototype for `public` FotoSlider `crossFade` effect
 * @TODO fix fast-move bug where no item is left visible ...
 */
FotoSlider.plugin('crossFade', function(instance){
	instance._index = FotoSlider.instances.length;
	instance.find('.item').each(function(idx, el){
		var item 		= $(this);
		item.attr('itemindex', idx);
		item.image 		= item.find('img')[0];
		item.caption 	= item.find('.caption')[0];
		instance.css({
			'height': Math.max(instance.height(),$(item.image).height())+'px'
		});
		item.css({
			'opacity': 0, 
			'display': 'none'
		});
		//console.log($(item.image).height()); // does not work ...?
		item.bind('click', function(evt){
			if(idx != instance.nextIndex){
				if(evt.originalEvent){
					// we have a user-click, postpone FotoSlider.autoNext() for this instance
					FotoSlider.postpone(instance._index);
				}
				var offItem = item;
				var onIndex = (instance.nextIndex >= 0) ? instance.nextIndex : ((idx+1)%(instance.items.length));
				var onItem 	= $(instance.items[onIndex]);
				offItem.removeClass('active')
					.animate({
						'opacity' 	: 0, 
						'height' 	: 0,
						'top' 		: '100%'
					}, 
					instance.speed, 
					function(){
						//
						$(this).css({'display': 'none', 'top': 0})
							.trigger('mouseleave');
					});
				onItem.addClass('active')
					.css({'display': 'block'})
					.animate({
						'opacity' 	: 1, 
						'height' 	: instance.height()+'px',
						'top' 		: 0
					}, 
					instance.speed, 
					function(){
						//
						$(this).trigger('mouseenter');
						var __idx = $(this).attr('itemindex');
						setTimeout('FotoSlider.fakeMouseLeave('+instance._index+','+__idx+')', Math.max(instance.autoplayInt/2, 0));
					});
			}
			
			instance.nextIndex = -1;
			
			})
			.bind('mouseleave', function(evt){
				item.find('.caption').animate({
						'opacity': 0,
						'bottom': 0
					}, 
					Math.round(instance.speed*2/3), 
					function(){
						//
				});
			})
			.bind('mouseenter', function(evt){
				item.find('.caption').animate({
					'opacity': 0.9,
					'bottom': '18px'
					}, 
					Math.round(instance.speed*2/3), 
					function(){
						//
				});
			});
		item.trigger('mouseleave');
		instance.items.push(item);
	});
	
	$(instance.items[instance.items.length-1])
		.addClass('active')
		.trigger('click');
});


/*
 * kick-off one (or more) FotoSlider instances for a plugin-specific configuration
 */

$(document).ready(function(){

	var myFSConfig = {
		selector	: '.fotoslider', 
		speed 		: 650, 			// transition-speed
		autoplay 	: true,
		autoplayInt : 5000, 		// next image in ... ms
		effect 		: 'crossFade' 	// da's eigenlijk de enige die tot nu toe gebouwd is
	};
	FotoSlider.init(myFSConfig);
});

