var Carousel = function(configParams, callback){
	 //default settings for the carousel
    var config = {
		startIndex	: 0, //index on which to start
        speed       : 300, //animation speed in ms
        direction   : 'horizontal', //direction of animation, 'horizontal' or 'vertical' are valid options
        container   : null, //DOM obj of the <UL> where we work with
        continues   : false, //determines whether to continue after last element in an loop
        autoLoopInterval    : 0, //timer for automated scroll, 0 for none
        callback    : function(){},
                
        bind : function(params, callback){
            if(params){
                for(param in params){
                    eval("config." + param + " = params." + param);
                }
            }
            if(typeof(callback) == "function"){
                config.callback = callback;
            }
            //config binding done
            config.init = true;
        },
        init : false, //determines if the binding of config is done
        dummy : null //to not forget the appending of the extra , after the last variable
    }; 
    //bind the configuration
    config.bind(configParams, callback);
	
	var priv = {
		curIndex : -1,
		stepSize : 0,
		locked	 : false,
		$container : $(config.container),
		$carousel : null,
		$items   : null,
		validDOM : true,
		
		init : function(){
			Log.Info("Carousel init");
		
			//test if we actually have an object to work with
			priv.$carousel = priv.$container.find(".carousel");
			priv.$items = priv.$carousel.children();
			
			Log.Debug(priv.$items);
			
			if(!priv.$carousel.get(0) || priv.$items.length == 0){
				priv.validDOM = false;
				return false;
			}
			
			//initially hide the object until all sizing is done
			priv.$container.css({"opacity" : "0", "overflow" : "hidden", "position" : "relative"});
			priv.$carousel.css({"position" : "absolute"});
			
			//set the size of the carousel
			var totHeight = 0;
			var totWidth = 0;
			for(var i = 0; i < priv.$items.length; i++){
					totHeight += $(priv.$items[i]).height();
					totWidth += $(priv.$items[i]).width();
				}
			if(config.direction == 'horizontal'){
				var width = 0;
				priv.$carousel.width(totWidth);
			}
			else if (config.direction == 'vertical'){
				priv.$carousel.height(priv.$items[priv.$items.length - 1].offsetHeight);
			}
			
			Log.Debug($(priv.$items[config.startIndex]));
			
			priv.$container.width($(priv.$items[config.startIndex]).width()).height($(priv.$items[config.startIndex]).height());
			
			//move to inital item and make visible
			Log.Debug("init");
			priv.to(config.startIndex, function(){
				priv.$container.animate({"opacity" : "1"}, config.speed, function(){});
				Log.Debug("done");
			});
		},
		
		to : function(newIndex, callback){
			Log.Debug("Moving: curIndex : " + priv.curIndex + " newIndex : " + newIndex);
			
			//check if we have valid objects
			if(!priv.validDOM){
				Log.Info("Not moving, no valid DOM");
				return false;
			}
			
			
			//test if we can actually move
			if(newIndex < 0 || newIndex >= priv.$items.length || newIndex == priv.curIndex){
				Log.Info("Not moving, no valid or same index. newIndex : " + newIndex + ", itemsLength : " + priv.$items.length + ", curIndex : " + priv.curIndex);
				return false;
			}
			
			//test if we are locked
			if(priv.locked){
				Log.Info("Not moving, carousel: locked");
				return false;
			}
			//now lock and make the animation
			priv.locked = true;
			//set the current index
			priv.curIndex = newIndex;
			
			//make the animation
			Log.Debug("animation direction : " + config.direction);
			if(config.direction == 'horizontal'){
				Log.Debug("offsetLeft : " + $(priv.$items[newIndex]).offset().left);
				priv.$carousel.animate({"left" : "-" + priv.$items[newIndex].offsetLeft }, config.speed, function(){priv.done(callback)});
			}
			else if (config.direction == 'vertical'){
				Log.Debug("offsetTop : " + $(priv.$items[newIndex]).offset().top);
				priv.$carousel.animate({"top" : "-" + $(priv.$items[newIndex]).offset().top + "px"}, config.speed, function(){priv.done(callback)});
			}
			
		},
		
		done : function(callback){
			priv.$container.animate({"height" : $(priv.$items[priv.curIndex]).height() + "px"}, config.speed, function(){priv.locked = false;});
			if(typeof(callback) == "function"){
				callback();
			}
		},
		
		next : function(){
			priv.to(priv.curIndex + 1);
		},
		
		prev : function(){
			priv.to(priv.curIndex - 1);
		}
	};
	priv.init();
	
	return {
		Next : function(){
			priv.next();
		},
		
		Prev : function(){
			priv.prev();
		},
		
		To : function(newIndex){
			priv.to(newIndex);
		}
	}
};