// Hitch plugin test
(function($) {
    $.fn.hitch = function(ev, fn, scope) {
        return this.bind(ev, function() {
            return fn.apply(scope || this, Array.prototype.slice.call(arguments));
        });
    };
})(jQuery);

var carouselController = {
	currentSliderObj: null,  
	sliderStartX: 0,
	slideTo: 0,
	leftCallbacks : {},
	rightCallbacks : {},
	pageIndexs : {},
	
	initCarousel : function() {
		var carousels = jQuery('.carouselstrip');
		for(var i=0; i<carousels.length; i++) {
			var carousel = jQuery(carousels[i]); 
			var count = carousel.children().length;
			if(carousel.children(':first-child').css('width') == null) {
				continue;
			}			
			var itemWidth = parseInt(carousel.children(':first-child').css('width')); 
			carousel.css('width', (count*itemWidth)+'px');
			var idPart = this.getIdPart(carousels[i].id)			
			this.setHandlerWidth(idPart);
			this.pageIndexs[idPart] = 0;
			this.resetCarouselSlide(carousels[i].id);
		}
		this.setArrowsStates();
	},
	setHandlerWidth : function(idPart) {
		// scale the handler to match the number of items
		var carouselData = this.getCarouselData(idPart);
		var sliderWindow = carouselData.sliderWindowWidth;
		var sliderStrip = carouselData.sliderStripWidth;
		var factor = sliderStrip / sliderWindow;		
		// If the viewport does not need to scroll, set the scrollbar to maximum
		if(factor <= 1) {
			carouselData.handle.css('width',carouselData.sliderBarWidth+'px');
			return;			
		}
		var handleWidth = Math.round(carouselData.sliderBarWidth / factor);
		if(handleWidth < 30) {
			handleWidth = 30;
		}
		carouselData.handle.css('width', handleWidth);		
	},
	handleSliderbarClick : function(e) {
		obj = e.currentTarget;
		var idPart = this.getIdPart(obj.id);
		var data = this.getCarouselData(idPart);
		// Get the offset of the sliderbarcontainer
		var offsetLeft = parseInt(data.sliderBar.attr('offsetLeft'));
		// Get the coordinates of the click
		var clickCoords = parseInt(e.pageX);
		// The position to animate the handle to
		var barPos = clickCoords - offsetLeft;
		this.scrollToPosition(barPos, data);
		return false;
	},
	scrollToPosition : function(coords, carouselData) {
		// The amount the slider can slide
    	var sliderRange = carouselData.sliderBarWidth - carouselData.handleWidth;
    	
    	coords -= Math.round(carouselData.handleWidth/2);    	
    	// Check the bounds and position the handle
        if(coords < 0) {
        	coords = 0;
        } else if(coords > sliderRange) {
        	coords = sliderRange;
        }
        
        // calculate the steps and set the scroller to the correct position
        var scrollingRange = carouselData.sliderStripWidth -  carouselData.sliderWindowWidth;
        var scrollingStep = scrollingRange/sliderRange;
        
        var sliderStep = sliderRange/scrollingRange;
        
        var scrollingPos = Math.ceil(coords * scrollingStep);
        scrollingPos = this.roundScrollingAction(scrollingPos, carouselData);
        this.slideTo = scrollingPos;
		carouselData.sliderWindow.animate({'scrollLeft': scrollingPos}, 500);
        carouselData.handle.animate({'left': (sliderStep*scrollingPos)}, 500, function() {
        	setTimeout("carouselController.setArrowsStates()", 300);
        });
	},
	getCarouselData : function(idPart) {
		// The visible window
		var sliderWindow = jQuery('#'+idPart+'_sliderwindow');
		// All the items
		var sliderStrip = jQuery('#'+idPart+'_strip');
		// The value of scrollleft
		var scrollLeft = parseInt(sliderWindow.attr('scrollLeft'));
		// The width of the visible window
		var sliderWindowWidth = parseInt(sliderWindow.css('width'));
		// The width of all the items
		var sliderStripWidth = parseInt(sliderStrip.css('width'));
		// The width of one item
		var itemWidth = parseInt(sliderStrip.children(':first-child').css('width'));
		// The handle
		var handle = jQuery('#'+idPart+'_sliderhandle');
		// The width of the draggable handle
		var handleWidth = parseInt(handle.css('width'));
		// The sliderbar
		var sliderBar = jQuery('#'+idPart+'_sliderbar');
		// The width of the bar in which the handle resides
		var sliderBarWidth = 0;
		// if sliderbar is not available, don't do stuff
		if (!isNaN(parseInt(sliderBar.css('width')))) {
			sliderBarWidth = parseInt(sliderBar.css('width'));
		}
		// The scrollingrange of the window
        var scrollingRange = sliderStripWidth - sliderWindowWidth;
        // The amount the slider can slide
    	var sliderRange = sliderBarWidth - handleWidth;        
    	// The scrollingstep is the unit for the window to slide per scrollbar step
    	var scrollingStep = sliderRange/scrollingRange;		
		
		var carouselData = {
			scrollLeft: scrollLeft,
			sliderWindowWidth: sliderWindowWidth,
			sliderStripWidth: sliderStripWidth,
			sliderWindow: sliderWindow,
			itemWidth: itemWidth,
			handleWidth: handleWidth,
			sliderBarWidth : sliderBarWidth,
			handle : handle,
			scrollingRange: scrollingRange,
			sliderRange: sliderRange,
			scrollingStep: scrollingStep,
			sliderBar: sliderBar
		};
		return carouselData;	
	},
	getIdPart : function (objId) {
		var arr = objId.split("_");
		if(arr.length>0) {
			var part = "";
			for(var i=0;i<arr.length-1;i++) {
				part += arr[i]+"_"; 
			}
			return part.substring(0, part.length-1);
		}
		return "";
	},
	setArrowsStates : function () {
		var carousels = jQuery('.carouselstrip');
		for(var i=0; i<carousels.length; i++) {
			var disableLeft = false;
			var disableRight = false;	
			var idPart = carouselController.getIdPart(carousels[i].id);
			var carouselData = carouselController.getCarouselData(idPart);
			var carousel = jQuery(carousels[i]);
			var itemWidth = parseInt(carousel.children(':first-child').css('width'));
			if(carouselData.scrollLeft <= 0) {
				disableLeft = true;
			}
			if(carouselData.scrollLeft >= carouselData.scrollingRange) {
				disableRight = true;
			}
			if(carouselData.sliderWindowWidth >= carouselData.sliderStripWidth) {
				disableLeft = true;
				disableRight = true;
			}
			if(disableLeft) {
				jQuery('#'+idPart+'_'+'leftarrow').addClass('inactive');
				jQuery('#'+idPart+'_'+'leftarrowlink').addClass('inactive');
			} else {
				jQuery('#'+idPart+'_'+'leftarrow').removeClass('inactive');
				jQuery('#'+idPart+'_'+'leftarrowlink').removeClass('inactive');
				jQuery('#'+idPart+'_'+'leftarrowlink img').addClass('roll_image');
			}
			if(disableRight) {
				jQuery('#'+idPart+'_'+'rightarrow').addClass('inactive');
				jQuery('#'+idPart+'_'+'rightarrowlink').addClass('inactive');
			} else {
				jQuery('#'+idPart+'_'+'rightarrow').removeClass('inactive');
				jQuery('#'+idPart+'_'+'rightarrowlink').removeClass('inactive');		
			}
		}
	},
	roundScrollingAction : function(scrollValue, carouselData) {
		var roundedScrollValue = scrollValue/carouselData.itemWidth;
		roundedScrollValue = Math.round(roundedScrollValue)*carouselData.itemWidth;
		scrollValue = roundedScrollValue;
		return scrollValue;
	},
	
	resetCarouselSlide : function(carouselId) {
		var idPart = this.getIdPart(carouselId);
		var carouselData = this.getCarouselData(idPart);
		carouselData.sliderWindow.attr({'scrollLeft': 0});
		carouselData.handle.css({'left': 0});		
	},
	resetCarouselPosition: function(carouselId) {
		var carouselData = this.getCarouselData(carouselId);
		carouselData.sliderWindow.attr({'scrollLeft': 0});
		carouselData.handle.css({'left': 0});		
	},
	scrollCarouselPositionTo : function(carouselId, pos){
		var carouselData = this.getCarouselData(carouselId);
		carouselData.sliderWindow.attr({'scrollLeft': pos});
		carouselData.handle.css({'left': pos});
		this.slideTo = pos;
		this.setArrowsStates();
	},
	scrollCarouselLeft : function(event) {
		var idPart = this.getIdPart(event.currentTarget.id);
		var carouselData = this.getCarouselData(idPart);	
		if(carouselData.scrollLeft <= 0) {
			this.callLeftCallback(idPart);
			return false;
		}
		var scrollValue = carouselData.scrollLeft-carouselData.sliderWindowWidth;
		scrollValue = this.roundScrollingAction(scrollValue, carouselData);
		if(scrollValue < 0) {
			scrollValue = 0;
		}
        var scrollingPos = Math.ceil(scrollValue * carouselData.scrollingStep);
        if(scrollingPos <= 0) {
        	scrollingPos = 0;
        }
        this.slideTo = scrollValue;
				carouselData.sliderWindow.animate({'scrollLeft': scrollValue}, 500, function(){
        		setTimeout("carouselController.setArrowsStates()", 300);
        });
        carouselData.handle.animate({'left': scrollingPos}, 500, function() {
        	setTimeout("carouselController.setArrowsStates()", 300);
        });
        this.pageIndexs[idPart] = this.pageIndexs[idPart] - 1;
        this.callLeftCallback(idPart);
        return false;
	},
	scrollCarouselRight : function(event) {
		var idPart = this.getIdPart(event.currentTarget.id);
		var carouselData = this.getCarouselData(idPart);
		var maxScroll = carouselData.sliderStripWidth - carouselData.sliderWindowWidth;
		if(maxScroll <= 0) {
			maxScroll = 0;
		}
		if(carouselData.scrollLeft >= maxScroll) {
			this.callRightCallback(idPart);
			return false;
		}
		var scrollValue = carouselData.scrollLeft+carouselData.sliderWindowWidth;
		scrollValue = this.roundScrollingAction(scrollValue, carouselData);
		if(scrollValue >= maxScroll) {
			scrollValue = maxScroll;
		}
        var scrollingPos = Math.ceil(scrollValue * carouselData.scrollingStep);
        if(scrollingPos > carouselData.sliderRange) {
        	scrollingPos = carouselData.sliderRange;
        }
        this.slideTo = scrollValue;
        carouselData.sliderWindow.animate({'scrollLeft': scrollValue}, 500, function(){
        		setTimeout("carouselController.setArrowsStates()", 300);
        });
        carouselData.handle.animate({'left': scrollingPos}, 500, function() {
        		setTimeout("carouselController.setArrowsStates()", 300);
        });
        this.pageIndexs[idPart] = this.pageIndexs[idPart] + 1;
        this.callRightCallback(idPart);
        return false;
	},
	
	callLeftCallback : function(idPart) {
		if(this.leftCallbacks[idPart] != null) {
			this.leftCallbacks[idPart](idPart);			
		}	
	},
	
	callRightCallback : function(idPart) {
		if(this.rightCallbacks[idPart] != null) {
			this.rightCallbacks[idPart](idPart);			
		}	
	},	
	
	dragSlider : function(e) {
		if(this.currentSliderObj != null) {
			var idPart = this.getIdPart(this.currentSliderObj.id);
			var carouselData = this.getCarouselData(idPart); 
			
			// The amount the slider can slide
	    	var sliderRange = carouselData.sliderBarWidth - carouselData.handleWidth;
	    		
	    	// The value sent by the mouse
	    	var x = e.pageX - this.sliderStartX;
	    	
	    	// Check the bounds and position the handle
	        if(x < 0) {
	            x = 0;
	        } else if(x > sliderRange) {
	            x = sliderRange;
	        }
	        jQuery(this.currentSliderObj).css('left',x+'px');
	        // calculate the steps and set the scroller to the correct position
	        var scrollingRange = carouselData.sliderStripWidth -  carouselData.sliderWindowWidth;
	        var scrollingStep = scrollingRange/sliderRange;
	        var scrollingPos = Math.ceil(x * scrollingStep);
	        carouselData.sliderWindow.attr('scrollLeft', scrollingPos);
	    }
	},
	startSlider : function(e) {
		this.currentSliderObj = e.currentTarget;
	    this.sliderStartX = parseInt(e.pageX) - parseInt(jQuery(e.currentTarget).css('left'));
	    return false;
	},
	stopSlider : function stopSlider(e) {
		// Prevent updating the arrows when not neccessary
		if(this.currentSliderObj != null) {
			this.setArrowsStates();
		}
        this.currentSliderObj = null;
	},
	
	setLeftCallback : function(carouselId, leftCallback) {
		var idPart = this.getIdPart(carouselId);		
		this.leftCallbacks[idPart] = leftCallback;
	},			
	
	setRightCallback : function(carouselId, rightCallback) {
		var idPart = this.getIdPart(carouselId);
		this.rightCallbacks[idPart] = rightCallback;
	}
}

function initCarouselItems() {
	jQuery('.singstarcarouselitem').hover(function(){
		jQuery(this).css('zIndex', 100);
		var albumImage = jQuery(this).children('.singstaralbumimage').css({height : '132px', width : '132px', top : '-9px', left : '-4px'});
		jQuery(this).children('.singstarcarouseloverlay').hide();
		jQuery(this).children('.singstaralbumimagehover').show();
		if(this.className.indexOf('singstarlastrow') > 0) {
			albumImage.css('top','-74px');
		}
	},
	function(){
		jQuery(this).css('zIndex', 0);
		var albumImage = jQuery(this).children('.singstaralbumimage').css({height : '101px', width : '101px', top : '6px', left : '11px'});
		jQuery(this).children('.singstarcarouseloverlay').show();
		jQuery(this).children('.singstaralbumimagehover').hide();		
	});
}

jQuery('document').ready(function() {
	// Set the width for the carousel strip
	
	carouselController.initCarousel();
	
	// Bind a click for the left arrow of the carousel
	jQuery('.carouselleftarrow a').hitch('click' , carouselController.scrollCarouselLeft, carouselController);
	
	// Bind a click for the right arrow of the carousel	
	jQuery('.carouselrightarrow a').hitch('click', carouselController.scrollCarouselRight, carouselController);

	// Bind a click for the sliderhandle arrow of the carousel
	jQuery('.carouselsliderhandle').hitch('mousedown', carouselController.startSlider, carouselController);
	
	// Bind a click for the sliderbar of the carousel
	jQuery('.carouselsliderbar').hitch('mousedown', carouselController.handleSliderbarClick, carouselController);
	
	// Bind the mouseup and mousemove events
	jQuery(document).hitch('mouseup', carouselController.stopSlider, carouselController);
	jQuery(document).hitch('mousemove', carouselController.dragSlider, carouselController);	
});
