/*
 * ReelInstance - an instance representing each reel of the given machine
 * 
 * @param id - the id assigned to this instance of a reel
 * @param image - the image used to represent the reel strip
 * 
 * @return none
 */
function ReelInstance(id, image)
{
	this.id = id;
	this.image = new Image();
	this.imageName = image;
	this.timerId = undefined;
	this.positionX = 0; // if vertical reels then this should always be 0
	this.positionY = 0;
	this.symbolsShowing = 0; // number of symbols showing on the screen for this reel
	this.totalSymbols = 0; // total symbols for the reel strip
	this.symbolHeight = 0; // the height of each symbol on the strip
	this.symbolWidth = 0; // the width of each symbol on the strip
	this.symbolSpacing = 0; // the spacing between symbols
	this.symbolPadding = 0; // the padding (top/bottom) which may be half of the spacing on each end.
	this.parentHeight = 0; // calculated
	this.canvasElement = null;
	this.currentSymbol = 1; // start with the current symbol as the first in the reel
	this.bounceReels = false;
	this.bounceInProgress = false;
	this.bounceAmount = 0.5; // 1/4 of a symbol
	this.bounceSpeed = 100; // speed of animation in milliseconds
	this.startSymbol = 0;
	this.facadeComplete = true;
	this.reelReady = null;
	this.reelFinishedSpinningCallback = null;
	
	this.getFacadeComplete = function ()
	{
		return this.facadeComplete;
	};
	
	this.setBounce = function (bounce)
	{
		this.bounceReels = bounce;
	};
	
	this.setBounceSpeed = function (speed)
	{
		this.bounceSpeed = speed;
	};
	
	this.setBounceAmount = function (amount)
	{
		this.bounceAmount = amount;
	};
	
	this.setSymbolsShowing = function (numSymbols)
	{
		this.symbolsShowing = numSymbols;
	};
	
	this.setTotalSymbols = function (stops)
	{
		this.totalSymbols = stops;
	};
	
	this.setSymbolHeight = function (height)
	{
		this.symbolHeight = height;
	};
	
	this.setSymbolWidth = function (width)
	{
		this.symbolWidth = width;
	};
	
	this.setSymbolSpacing = function (spacing)
	{
		this.symbolSpacing = spacing;
	};
	
	this.setSymbolPadding = function (padding)
	{
		this.symbolPadding = padding;
	};
	
	this.drawReel = function ()
	{
		var context = this.canvasElement.getContext('2d');
		
		// parent height should be the number of symbols showing * symbol height + symbol spacing
		// this assumes the padding top and bottom equals the spacing
		this.parentHeight = (this.symbolHeight + this.symbolSpacing) * this.symbolsShowing;

		this.canvasElement.width = this.image.width;
		this.canvasElement.height = this.parentHeight;
		
	    context.clearRect(0, 0, this.image.width, this.parentHeight);
	    context.drawImage(this.image, 0, 0, this.image.width, this.parentHeight, 0, 0, this.image.width, this.parentHeight);
	    
	    if (this.reelReady != null)
	    {
	    	this.reelReady();
	    }
	};
	
	this.resetReel = function (userCallback)
	{
		var thisObj = this;
		this.canvasElement = document.getElementById(this.id);
		this.reelReady = userCallback;
		this.image.onload = function () { thisObj.drawReel(); };
		this.image.src = this.imageName;
	};
	
	this.animateReel = function ()
	{
		var context = this.canvasElement.getContext('2d');

		// Move it on over
	    this.positionY += this.symbolHeight * 2;
	    
	    // Draw from the reel top down (source 0, 0, width, height
	    							//  destination positionX, positionY, image.width, parentHeight)
	    if (this.positionY < this.parentHeight)
	    {
//		    context.clearRect(0, 0, this.image.width, this.parentHeight);
		    
		    context.drawImage(this.image, 0, 0, this.image.width, this.parentHeight - this.positionY,
		    		this.positionX, this.positionY, this.image.width, this.parentHeight - this.positionY);

		    // image height is 1890, so we need to then draw the bottom part of the image first
			// such as destination 0 to (432 - y), using a source of image.height - (432 - y)
		    // technically if positionY is zero then this isn't needed however is it worth the if/then ?  Probably not given the first part of animate makes it non zero
		    context.drawImage(this.image, 0, this.image.height - this.positionY, this.image.width, this.positionY,
		    		this.positionX, 0, this.image.width, this.positionY);
//	    	this.startTimer();
	    }
	    else if (this.positionY < this.image.height) // don't go past our image boundary
	    {
	    	var sy = this.image.height - this.positionY - this.parentHeight;
	    	
//		    context.clearRect(0, 0, this.image.width, this.parentHeight);
		    
	    	if (sy < 0)
	    	{
	    		sy = this.image.height + sy; // roll it

	    		// the image remainder is less then the current reel view window so , we need to again do dual images
		    	context.drawImage(this.image, 0, 0, this.image.width, this.parentHeight,
		    			this.positionX, sy, this.image.width, this.parentHeight);
		    	context.drawImage(this.image, 0, this.image.height - this.positionY, this.image.width, sy,
		    			this.positionX, 0, this.image.width, sy);
	    	}
	    	else
	    	{
		    	// in this case the beginning of the reel isn't display at all (off screen) so we map to destination of 0, 0, width, parentHeight from a piece of the image
		    	context.drawImage(this.image, 0, sy, this.image.width, this.parentHeight,
		    			this.positionX, 0, this.image.width, this.parentHeight);
	    	}
//	    	this.startTimer();
	    }
	    else
	    {
	    	// show final position of reel
	    	this.stopReel();

	    	this.gotoSymbol();	    	
	    }	    
	};
	
	this.gotoSymbol = function ()
	{
		var context = this.canvasElement.getContext('2d');
	    var dx = this.image.width - this.symbolWidth;
	    var centerY = this.parentHeight / 2;

//	    context.clearRect(0, 0, this.image.width, this.parentHeight);
	    
	    /*
	     * If we are bouncing reels and there currently isn't one being done...
	     */
	    if (this.bounceReels == true && this.bounceInProgress == false)
	    {
//	    	alert('Bounce starting');
	    	if (this.startSymbol != this.currentSymbol)
	    	{
		    	this.bounceInProgress = true;
	    		this.startSymbol = this.currentSymbol;
	    		this.currentSymbol -= this.bounceAmount;
	    	}
	    }
	    
    	// I need to be able to place the center of my symbol with the center of the reel
    	// First we need to find the center of the symbol
    	// then calculate how far into the symbol we are.
    	var symbolCenter = this.symbolHeight / 2;
    	var symbolPosition = ((this.currentSymbol - 1) * this.symbolHeight) + ((this.currentSymbol - 1) * this.symbolSpacing);
    	if (symbolPosition < 0)
    		symbolPosition = 0;
    	var symbolSpread = Math.floor(this.symbolsShowing / 2);
    	var symbolOffset = ((this.symbolHeight + this.symbolSpacing) * symbolSpread);
//       	var targetPosition = centerY - symbolCenter - this.symbolPadding;
       	var targetLength = centerY + symbolCenter + this.symbolPadding; // we are offsetting the image by these so add it in
    	
    	if (symbolOffset <= symbolPosition)
    	{
    		// need to handle the end of the reel strip where we are on the last symbol and have to wrap the beginning
    		context.drawImage(this.image, 0, symbolPosition - symbolOffset, this.image.width, this.parentHeight,
    				0, 0, this.image.width, this.parentHeight);
    				
    		var rollOver = this.totalSymbols - symbolSpread;
    		if (this.currentSymbol >= rollOver)
    		{
    			var fudge = 0;
    			fudge = (this.currentSymbol - rollOver) * (this.symbolHeight + this.symbolSpacing);
    			var offset = (this.totalSymbols - this.currentSymbol) * (this.symbolHeight + this.symbolSpacing);
    			 
	    		context.drawImage(this.image, 0, 0, this.image.width, fudge,
    				0, targetLength + offset, this.image.width, fudge); 
    		}
    	}
    	else
    	{
        	var fudge = 0;
        	if (this.currentSymbol <= this.symbolsShowing)
        	{
        		fudge = (this.symbolHeight + this.symbolSpacing) * (this.symbolsShowing - this.currentSymbol - 1);
        	}

        	// Display the above the first part of the strip - need the padding to offset the 1/2 at top
        	// we need to display at least one symbol above - this will display the end of the reel strip X far down
        	if (this.currentSymbol <= symbolSpread)
        	{
        		context.drawImage(this.image, 0, this.image.height - fudge, this.image.width, fudge,
        				0, 0, this.image.width, fudge);
        	}

    		// need to handle this case where we are at the beginning of the reel strip and need
    		// to display it then add in the end of the strip above it
        	context.drawImage(this.image, 0, 0, this.image.width, targetLength,
        			0, fudge, this.image.width, targetLength);
    	}
    	
    	var linearGradient = context.createLinearGradient(0, 0, this.symbolWidth, this.symbolHeight);
    	
    	linearGradient.addColorStop(0.0, "red");
    	linearGradient.addColorStop(1.0, "white");
    	
    	context.strokeStyle = linearGradient; //'#FF0000';
    	context.lineWidth = 4;
    	context.strokeRect(dx, centerY - symbolCenter, this.symbolWidth, this.symbolHeight);
    	context.moveTo(dx, centerY - 2);
    	context.lineTo(dx + this.symbolWidth, centerY + 2);    	
    	context.stroke();
    	
	    if (this.bounceReels == true)
	    {
	    	if (this.currentSymbol < this.startSymbol)
	    	{
		    	this.currentSymbol += 0.05;
		    	if (this.currentSymbol > this.startSymbol)
		    	{
		    		this.currentSymbol = this.startSymbol;
		    	}
		    	var thisObj = this;
				setTimeout(function() {thisObj.gotoSymbol();}, thisObj.bounceSpeed);
	    	}
	    	else
	    	{
	    		this.stopReel();
	    		this.bounceInProgress = false;
		    	if (this.reelFinishedSpinningCallback != null)
		    	{
		    		this.reelFinishedSpinningCallback();
		    	}
	    	}
	    }
	    else
	    {
	    	if (this.reelFinishedSpinningCallback != null)
	    	{
	    		this.reelFinishedSpinningCallback();
	    	}
	    }
	};
	
	this.stopReel = function ()
	{
		clearInterval(this.timerId);
		this.timerId = undefined;
		this.positionY = 0; // need to have the gotoStop method set Y
		this.facadeComplete = true; // may need to move this due to the reel bounce
	};

	this.startTimer = function ()
	{
		var thisObj = this;
		
		if (this.timerId != undefined)
		{
			clearInterval(this.timerId);
			this.timerId = undefined;
		}
		this.timerId = setInterval(function() {thisObj.animateReel();}, 100);
	};
	
	this.spinReel = function (stop, reelFinishedCallback)
	{
		this.reelFinishedSpinningCallback = reelFinishedCallback;
		this.currentSymbol = stop;
		this.facadeComplete = false;
		this.startSymbol = 0; // used for bouncing
		this.startTimer();
	};
}

