/**
*	Requires element.js
*	
*/
function elementSlider() {

	var thisObj = this;
	
	this.idNrOfSlider	
	this.nrOfPixelsToSlidePrevious = 0;
	this.nrOfPixelsToSlideNext = 0;		
	this.idOfElementToSlide;
	this.idNrOfElementInFocus = 1;
	this.widthOfInnerElements;
	this.nrOfElements;
	this.slideDurationOne;
	this.slideDurationAll;
	this.marginLeftAndRightOfElements;
	
	// Keeps track of the current margin left value so we dont have to access the object every time
	this.marginLeftOfElementToSlide;
	
	// Container for functions to be run after a slide has finished
	this.functionsAfterSlide = new Array();
	
	// The idNr of the next element to gain focus (the nr should be part of the elements id (id=...))
	this.idNrOfNextElementToGainFocus;
	
	// The margin left before we start a slide
	this.marginLeftBeforeSlide;
	
	// The amount of tme to use for the current slide (gets the value of either slideDurationOne or slideDurationAll)
	this.slideDuration;

	/**
	* @varIdNrOfSlider 						For use when accessing the slider elements. This nr should be part of the elements that uniqely identifies
	*										the elements for a slider.
	* @varNrOfPixelsToSlidePrevious			How many pixels to slide when sliding to the previous element
	* @varNrOfPixelsToSlideNext				How many pixels to slide when sliding to the next element (most likely the same as nrOfPixelsToSlidePrevious)
	* @varIdOfElementToSlide				The id of the elemnt to slide (id=...)
	* @varIdNrOfElementInFocus				The nr of the element in focus (used when accessing elements specific to an element)
	* @varWidthOfInnerElements				The width of the inner elements. This value has to be the same for all elements
	* @varNrOfInnerElements					How many elements we have in total
	* @varMarginLeftAndRightOfInnerElements	The left and right margin of the elements (this has to be the same for all)
	* @varlideOneDuration					How long the sliding of one element should last in miliseconds	
	* @varSlideAllDuration					How long the slide of all elements (slideToStart and slideToEnd) should last in miliseconds
	*/
	this.init = function(varIdNrOfSlider, varNrOfPixelsToSlidePrevious, varNrOfPixelsToSlideNext, varIdOfElementToSlide, varIdNrOfElementInFocus, varWidthOfInnerElements, varNrOfElements, varMarginLeftAndRightOfElements, varSlideDurationOne, varSlideDurationAll) {
		
		this.idNrOfSlider = varIdNrOfSlider;
		this.nrOfPixelsToSlidePrevious = varNrOfPixelsToSlidePrevious;
		this.nrOfPixelsToSlideNext = varNrOfPixelsToSlideNext;
		this.idOfElementToSlide = varIdOfElementToSlide;
		this.idNrOfElementInFocus = varIdNrOfElementInFocus;
		this.widthOfInnerElements = varWidthOfInnerElements;
		this.nrOfElements = varNrOfElements;
		this.slideDurationOne = varSlideDurationOne;
		this.slideDurationAll = varSlideDurationAll;
		this.marginLeftAndRightOfElements = parseInt(varMarginLeftAndRightOfElements);
		
		this.unsetSlideStartTime();
		
		// Lets make an element using the elementId
		this.elementToSlide = document.getElementById(varIdOfElementToSlide);
		
		// Get current margin-left of element to slide.
		this.marginLeftOfElementToSlide = parseInt(this.elementToSlide.style.marginLeft);
		
		// Get the width of the element that we are sliding
		this.widthOfElementToSlide = parseInt(this.elementToSlide.style.width);
		
		// If we have no set time for slideDurationAll
		if(this.slideDurationAll == false) {
		
			// Calculate the slide duration for all elements using
			// the nr of elements and the slide time for one element
			this.slideDurationAll = this.nrOfElements * (this.slideDurationOne/5);
		
		}
		
	}
	
	/**
	* Sets this.slideStartTime to the current timestamp.
	*/
	this.setSlideStartTime = function() {
	
		// Get the time when the slide starts
		this.slideStartTime = new Date().getTime();	
	
	}
	
	/**
	* Sets this.slideStartTime to false
	*/
	this.unsetSlideStartTime = function() {
	
		// Get the time when the slide starts
		this.slideStartTime = false;	
	
	}
	
	/**
	* Returns true if the slider is running (moving an element) and false if it is not
	*/
	this.slideIsRunning = function() {
	
		return this.slideStartTime != false;
	
	}	
	
	/**
	*
	*/
	this.startSlide = function(slideDirection) {
	
		// Lets only do a slide if we are not running one already
		if(!this.slideIsRunning()) {
	
			this.marginLeftBeforeSlide = this.getMarginLeftOfElementToSlide();
			
			// If we want to slide to the next element
			if(slideDirection == 'next') {
			
				// Calculate the nr of the next element
				this.idNrOfNextElementToGainFocus = this.idNrOfElementInFocus + 1;
				
				// If we will land outside the elements
				if(this.idNrOfNextElementToGainFocus > this.nrOfElements) {
				
					// Lets go back to the start
					this.idNrOfNextElementToGainFocus = 1;
					
					// We will use the slideToStart-function
					slideFunction = 'start';
				
				} else {
				
					// We will use the slideToNext-function
					slideFunction = 'next';
				
				}
	
			} else { // Slide direction is previous
			
				// Calculate the nr of the previous element
				this.idNrOfNextElementToGainFocus = this.idNrOfElementInFocus - 1;
				
				// If we will land outside the elements
				if(this.idNrOfNextElementToGainFocus < 1) {
				
					// Lets go to the end
					this.idNrOfNextElementToGainFocus = this.nrOfElements;
					
					// We will use the slideToEnd-function
					slideFunction = 'end';
	
				
				} else { // We are within boundaries
				
					// We will use the slideToPrevious-function
					slideFunction = 'previous';
				
				}
			
			}
			
			// Unfocus the currently focused element
			this.unfocusElement(this.idNrOfElementInFocus);	
			
			// Find out which slide function we want to run and run it
			switch(slideFunction) {
			
				case 'next' :
				
					this.slideToNext();
					break;
					
				case 'previous' :
				
					this.slideToPrevious();
					break;
					
				case 'start' :
				
					this.slideToStart();
					break;
					
				case 'end' :
				
					this.slideToEnd();			
					break;
			
			}
			
		}
	
	}
	
	/**
	*
	*/
	this.slideToNext = function() {
		
		nrOfPixelsToSlide = this.widthOfInnerElements + (this.marginLeftAndRightOfElements * 2);
		targetMarginLeft = (this.marginLeftOfElementToSlide - (this.widthOfInnerElements + (this.marginLeftAndRightOfElements * 2)));
		
		this.slideDuration = this.slideDurationOne;
		
		// Slide!
		this.slideHorizontal('next', nrOfPixelsToSlide, targetMarginLeft);
		
	}
	
	/**
	*
	*/
	this.slideToPrevious = function() {
		
		nrOfPixelsToSlide = this.widthOfInnerElements + (this.marginLeftAndRightOfElements * 2);
		targetMarginLeft = (this.marginLeftOfElementToSlide + (this.widthOfInnerElements + (this.marginLeftAndRightOfElements * 2)));
		
		this.slideDuration = this.slideDurationOne;		
		
		// Slide!
		this.slideHorizontal('previous', nrOfPixelsToSlide, targetMarginLeft);	
		
	}

	/**
	*
	*/
	this.slideToStart = function() {
	
		nrOfPixelsToSlide = ((this.nrOfElements - 1) * this.nrOfPixelsToSlideNext);
		targetMarginLeft = -(this.marginLeftAndRightOfElements);
		
		this.slideDuration = this.slideDurationAll;
		
		// Slide!
		this.slideHorizontal('previous', nrOfPixelsToSlide, targetMarginLeft);
	
	}
	
	/**
	*
	*/
	this.slideToEnd = function() {
	
		nrOfPixelsToSlide = ((this.nrOfElements - 1) * this.nrOfPixelsToSlideNext);
		targetMarginLeft = -(nrOfPixelsToSlide + this.marginLeftAndRightOfElements);
		
		this.slideDuration = this.slideDurationAll;
	
		// Slide!
		this.slideHorizontal('next', nrOfPixelsToSlide, targetMarginLeft);
	
	}	
	
	/**
	*
	*/
	this.addFunctionAfterSlide = function(functionCall) {
	
		this.functionsAfterSlide[this.functionsAfterSlide.length] = functionCall
	
	}
	
	/**
	*
	*/
	this.getMarginLeftOfElementToSlide = function() {
	
		return parseInt(this.elementToSlide.style.marginLeft);
	
	}
	
	/**
	*
	*/
	/**
	*
	*/
	this.slideHorizontal = function(direction, nrOfPixelsToSlide, targetMarginLeft) {
	
		// If we are not sliding
		if(this.slideStartTime == false) {
		
			// Set the start time
			this.setSlideStartTime();
		
		}
		
		// Calculate for how long the slide has been going on
		var elapsedSlideTime = new Date().getTime() - this.slideStartTime;
		
		// Caclulate how much we want to change the margin left by this time
		changePercentage = this.getCurveIncrement(elapsedSlideTime/this.slideDuration);
		
		// If we are moving to the next element (moving right)
		if(direction == 'next') {
			
			// Calculate the new margin left
			newMarginLeft = this.marginLeftBeforeSlide - parseInt(changePercentage * nrOfPixelsToSlide);

			// If the new left margin is below the target
			if(newMarginLeft < targetMarginLeft) {
				// Fall back to target
				newMarginLeft = targetMarginLeft;
			}
			
		} else { // We are moving to the previous element (moving left)

			// Calculate the new margin left			
			newMarginLeft = this.marginLeftBeforeSlide + parseInt(changePercentage * nrOfPixelsToSlide);
			
			// If the new left margin is above the target
			if(newMarginLeft > targetMarginLeft) {
				// Fall back to target
				newMarginLeft = targetMarginLeft;		
			}
			
		}
		
		if(!isNaN(newMarginLeft)) {

		// Set new margin left
		this.setMarginLeftOfSLiderElement(newMarginLeft);
		
		}
		
		// If the script has not executed the set amount of time
		if(elapsedSlideTime < this.slideDuration) {
		
			// Lets call the function again after the set amount of time
			this.timeout = setTimeout(function() { thisObj.slideHorizontal(nrOfPixelsToSlide, direction, targetMarginLeft); }, 0);		
		
		} else { // Script has executed for the set amount of time
		
			// Clear timeout
			clearTimeout(this.timeout);
			
			// Make sure that we have reached the target
			if(newMarginLeft != targetMarginLeft) {
			
				this.setMarginLeftOfSLiderElement(targetMarginLeft);
			
			}
			
			// Set focus on the newly focused element
			this.setFocusOnElement(this.idNrOfNextElementToGainFocus);
			
			var nrOfFunctionsAfterSlide = this.functionsAfterSlide.length;
			
			// Loop the functions to call after sliding is done
			for(var functionsAfterSlideIndex = 0; functionsAfterSlideIndex < this.functionsAfterSlide.length; functionsAfterSlideIndex++) {
			
				// Run function
				eval(this.functionsAfterSlide[functionsAfterSlideIndex]);
				
				// Rmeove the function form the array
				this.functionsAfterSlide[functionsAfterSlideIndex] = null;
			
			}
			
			// Unset the slideStartTime
			this.unsetSlideStartTime();
		
		}
		
	}
	
	/**
	*
	*/
	this.setMarginLeftOfSLiderElement = function(marginLeft) {
	
		// Set new margin left		
		this.elementToSlide.style.marginLeft = marginLeft + 'px';

		// Lets store the new margin left value
		this.marginLeftOfElementToSlide = marginLeft;	
	
	}
	
	/*
	*
	*/
	this.getCurveIncrement = function(percent) {
		
		return (1-Math.cos(percent*Math.PI)) / 2;
		
	}	
	
	/**
	* Actions to be taken when an element slides out of focus
	*/
	this.unfocusElement = function(idNrOfElement) {
	
		document.getElementById('elementSliderModule_' + this.idNrOfSlider + '_InnerDataWrapper_' + idNrOfElement).style.visibility = 'hidden';
	
	}
	
	/**
	* Actions to be taken when an element is placed in focus
	*/
	this.setFocusOnElement = function(idNrOfElement) {
	
		this.idNrOfElementInFocus = idNrOfElement;
		
		document.getElementById('elementSliderModule_' + this.idNrOfSlider + '_InnerDataWrapper_' + idNrOfElement).style.visibility = 'visible';
	
	}



}