// Miscellaneous initialization stuff I still have to organize, sprite maps, and color maps
invincibleColorMaps = [ { 0: null, 1: '#751222', 2: '#889294', 3: '#6B6840' },
                        { 0: null, 1: '#111A5F', 2: '#9FC0C1', 3: '#065F3E' },
                        { 0: null, 1: '#556779', 2: '#819976', 3: '#668612' },
                        { 0: null, 1: '#D6EFE5', 2: '#935BAA', 3: '#B75C51' },
                        { 0: null, 1: '#9851AE', 2: '#BDD796', 3: '#2557A9' },
                        { 0: null, 1: '#88AB9E', 2: '#C4D6CF', 3: '#46CFB2' },
                        { 0: null, 1: '#F3A346', 2: '#774204', 3: '#CF2C0E' },
                        { 0: null, 1: '#E89687', 2: '#2390BE', 3: '#5B5758' }];


Sprite.prototype.makeInvincible = function(colorMaps) {
    var rand = this.lastRandomColorIndex;
    while(rand == this.lastRandomColorIndex) {
        rand = randomArrayIndex(colorMaps);
	}
    this.setColorMap(colorMaps[rand]);
    this.lastRandomColorIndex = rand;
}

Mario.prototype.lastRandomColorIndex = randomArrayIndex(invincibleColorMaps);

// application variables
var keyIsDown = false;
var isJumping = false;
var movementFunction = null;
var framerate = 30;
var mainActorSize = 2;
var canvasWidth = 640;
var canvasHeight = 480;

// canvas handles
var stageCanvas		  = document.getElementById('canvas-stage');
var backgroundCanvas  = document.getElementById('canvas-background');

// create the sprites
var cloud      	= new Cloud(20, 20, backgroundCanvas).setPixelSize(4).render();
var cloud2     	= new Cloud(0, 140, backgroundCanvas).setPixelSize(2).render();
var mainSprite 	= new Mario(200, 0, stageCanvas).setDefaultPixelSize(mainActorSize).setPixelSize(mainActorSize).render();
var mainWalking = new MarioWalkingSprite(200, 0, stageCanvas).setDefaultPixelSize(mainActorSize).setPixelSize(mainActorSize);
var mainChgDir  = new MarioChangeDirectionSprite(200, 0, stageCanvas).setDefaultPixelSize(mainActorSize).setPixelSize(mainActorSize).render();

// Set up the Actors
var mainActor = new Actor();
	mainActor.
		setSpeedFactorX(1.1).
		setSpeedFactorY(1.1).
		setMinSpeedX(1).
		setMaxSpeedX(8).
		setMinSpeedY(0).
		setMaxSpeedY(4).
		setWidth(16).
		setHeight(16).
		setSpeed(0.5, 0).
		addSprite('idle', mainSprite, true).
		addSprite('walking', mainWalking, true).
		addSprite('changeDirection', mainChgDir, true).
		setPosition(0, 100);
var cloud2Actor = new Actor().addSprite('default', cloud2, true).setSpeed(3, 0);
var cloudActor  = new Actor().addSprite('default', cloud, true).setSpeed(1, 0);

// add the actors to the rendering queue
var actors = [cloudActor, cloud2Actor, mainActor];

// create animations (optional)
function backgroundAnimations() {
    cloudActor.step();
    cloud2Actor.step();
}

function stageAnimations() {
	if (keyIsDown && movementFunction != null) {
		movementFunction.call();
	} else if (!keyIsDown) {
		if (mainActor.speedX > mainActor.minSpeedX) {
			mainActor.speedFactorX = 1.25;
			mainActor.decelerateX();
			mainActor.stepX();
			if (!(mainActor.speedX > mainActor.minSpeedX)) {
				mainActor.speedFactorX = 1.1;
			}
		}
	}
}

// initialize everything
$(document).ready(function() {
	// configure the canvas
	$(backgroundCanvas).attr('tabindex', 1).attr('width', canvasWidth).attr('height', canvasHeight);
    $(stageCanvas).attr('tabindex', 2).attr('width', canvasWidth).attr('height', canvasHeight).focus().
		keydown(function(e) {
			if (keyIsDown)
				return;
			keyIsDown = true;
			movementFunction = function() { moveCharacter(e, mainActor) };
	    }).
		keyup(function(e) {
			keyIsDown = false;
			var currSpriteLabel = mainActor.getCurrentSpriteLabel();
			if (currSpriteLabel != 'idle') {
				if (mainActor.getCurrentSpriteLabel() == 'walking') {
					mainActor.currentSprite.stopAnimation();
				}	
				mainActor.setCurrentSprite('idle');
			}
		});

    mainActor.setPosition(0, stageCanvas.height - mainActor.currentSprite.getHeight());
    setInterval(main, 1000/framerate, 'canvas-stage');
});

function main(canvasID) {
    // complete animations
    backgroundAnimations();
	stageAnimations();
	
	// adjust sprite positions
    for (var i = 0; i < actors.length; i++) {
		adjustActorPositionWithinBounds(actors[i]);
	}
    
    // clear the canvases
	clearCanvas(backgroundCanvas);
	clearCanvas(stageCanvas);
    
    // draw the actor sprites
    for (var i = 0; i < actors.length; i++) {
		actors[i].draw();
	}
}

function moveCharacter(key, actor) {
	if (key.which == 37 || key.which == 39) { // left or right arrows (respectively)
		var direction = (key.which == 37) ? Sprite.SPRDIR_LEFT : Sprite.SPRDIR_RIGHT;
		if (direction != actor.getDirectionH()) {
			if (actor.minSpeedX == actor.speedX) {
				actor.setDirectionH(direction);
			} else {
				if (actor.getCurrentSpriteLabel() != 'changeDirection') {
					if (actor.getCurrentSpriteLabel() == 'walking') {
						actor.currentSprite.stopAnimation();
					}
					actor.setCurrentSprite('changeDirection');
				}
				actor.decelerateX();
			}
		} else {
			if (actor.getCurrentSpriteLabel() != 'walking') {
				actor.setCurrentSprite('walking');
				actor.currentSprite.startAnimation(actor.currentSprite);
			}
			actor.accelerateX();
		}
		actor.stepX();
	}
}

function adjustActorPositionWithinBounds(actor) {
	var canvas = actor.currentSprite.canvas;
	var totalWidth = actor.currentSprite.getWidth();
	var totalHeight = actor.currentSprite.getHeight();
	if (actor.x > canvas.width) {
		actor.x = -totalWidth;
	} else if (actor.x < -totalWidth) {
		actor.x = canvas.width;
	}
	if (actor.y > canvas.height) {
		actor.y = -totalHeight;
	} else if (actor.y < -totalHeight) {
		actor.y = canvas.height;
	}
}

function clearCanvas(canvas) {
	canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
}
