var TileType = {
    EMPTY: 0,
    WALL: 1,
    FLOOR: 2,
    DIAMOND: 3,
    START: 4,
    FINISH: 5
}

var Key = {
    LEFT: 37,
    RIGHT: 39,
    UP: 38,
    ENTER: 13
}

var Game = {
    active: false,
    started: false,
    increment: 0.5,
    friction: 0.5,
    maxSpeed: 3.0,
    keysDown: new Array(),
    score: 0
}

var Grid = {
    width: 31,
    height: 24,
    tileSize: 20,
    data: null,
    changesLeft: 10,
    container: null,
    totalWidth: 620,
    totalHeight: 480
}

var Hero = {
    x: 0,
    y: 0,
    xspeed: 0,
    yspeed: 0,
    jumping: false,
    falling: true,
    container: null,
    frameCount: 0,
    framesTotal: 6
}

function colliding(xdir, ydir) {
    
    var xdiff = Hero.x;
    var ydiff = Hero.y;
    
    if (xdir > 0) {
       xdiff = (Hero.x + Game.increment) + (Grid.tileSize / 2); 
    } else if (xdir < 0) {
       xdiff = Hero.x + (Game.increment * -1);
    }
    
    if (xdiff < 0 || xdiff > Grid.totalWidth) {
        return true;
    }
    
    if (ydiff < 0 || ydiff > Grid.totalHeight) {
       return true;
    }
    
    if (ydir > 0) {
       ydiff = (Hero.y + Game.increment) + Grid.tileSize; 
    } else if (ydir < 0) {
       ydiff = Hero.y + (Game.increment * -1);
    }
    
    var x = Math.floor(xdiff / Grid.tileSize);
    var y = Math.floor(ydiff / Grid.tileSize);

    switch (Grid.data[x][y]) {
        case TileType.WALL:
        case TileType.FLOOR:
            return true;
            break;
        case TileType.FINISH:
            Game.active = false;
            presentFinishPopup();
            break;
        default:
            return false;
            break;
    }
}

function initializeGrid() {
    do {
		var start = {
			x: Math.floor(Math.random() * 30),
			y: Math.floor(Math.random() * 23)
		}
	} while(start.x < 1 || start.y < 8);
				
	do {
		var finish = {
			x: Math.floor(Math.random() * 30),
			y: Math.floor(Math.random() * 23)
		}
	} while((finish.x == start.x && finish.y == start.y) && 
			finish.y < 1 || finish.x < 8);
			
	Hero.x = start.x;
	Hero.y = start.y;
	
	// Generate the grid matrix
	var g = new Array(Grid.width);
	for (var x = 0; x < g.length; x++) {
        g[x] = new Array(Grid.height);
        
        for (var y = 0; y < g[x].length; y++) {
            if (y > Math.floor(Math.random() * 8) ) {
                if (x == start.x && y == start.y) {
                    g[x][y] = TileType.START;
                } else if (x == finish.x && y == finish.y) {
                    g[x][y] = TileType.FINISH;
                } else {
                    if ((Math.random() * 2.5) < 1.2) {
                        if (y == 23) {
                            g[x][y] = TileType.FLOOR;
                        } else {
                            g[x][y] = TileType.WALL;
                        }
                    } else {
                        //g[x][y] = TileType.DIAMOND;
                    }
                }
            }
        }
    }
    
   Grid.data = g;
   
   drawGrid();
}

function drawGrid() {
    Grid.container = document.getElementById('grid');
	
	var tiles = '';
	for (var x = 0; x < Grid.width; x++) {
		for (var y = 0; y < Grid.height; y++) {						
			if (y > Math.floor(Math.random()*8) ) {
				tiles += '<div style="';
				tiles += 'left: ' + (x * Grid.tileSize) + 'px; ';
				tiles += 'top: ' + (y * Grid.tileSize) + 'px;" ';
		        
		        switch(Grid.data[x][y]) {
		            case TileType.WALL:
                        var blockType = 1;
                        
                        do {
                            blockType = Math.floor(Math.random()*5) + 1
                        } while (blockType == 0);
                         
		                tiles += 'class="block' + blockType + '" ';
		                break;
		            case TileType.FLOOR:
		                tiles += 'class="floor" ';
		                break;
		            case TileType.DIAMOND:
		                tiles += 'class="diamond" ';
		                break;
		            case TileType.START:
		                tiles += 'class="start" ';
		                break;
		            case TileType.FINISH:
		                tiles += 'class="finish" ';
		                break;
		        }
			
				tiles += '></div>';
				
				if (x == Hero.x && y == Hero.y) {
				    tiles += '<div style="';
    				tiles += 'left: ' + (x * Grid.tileSize) + 'px; ';
    				tiles += 'top: ' + (y * Grid.tileSize) + 'px;" ';
    				tiles += 'id="hero"></div>';
				}
			}
		}
	}
	
	Grid.container.innerHTML = tiles;
	Hero.container = document.getElementById('hero');
	
	Hero.x = Hero.x * Grid.tileSize;
	Hero.y = Hero.y * Grid.tileSize;
	
	gameLoop();
}

function inArray(element, arr) {
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] == element) 
            return true;
    }
    
    return false;
}

function removeFromArray(element, arr) {
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] == element)
            arr.splice(i, 1);
    }
    
    return arr;
}

function gameLoop() {
    if (inArray(Key.RIGHT, Game.keysDown)) {
        if (!colliding(Game.increment)) {
            if (Hero.xspeed <= Game.maxSpeed) {
                Hero.xspeed += Game.increment;
            }
        } else {
            Hero.xspeed = 0;
        }
    } else if (inArray(Key.LEFT, Game.keysDown)) {
        if (!colliding(Game.increment * -1)) {
            if (Hero.xspeed >= (Game.maxSpeed * -1)) {
                Hero.xspeed += Game.increment * -1;
            }
        } else {
            Hero.xspeed = 0;
        }
    } else {
        // No right / left keys are being pressed, so keep friction into account
        if (Hero.xspeed > 0) {
            if (!colliding(Game.friction)) {
                Hero.xspeed -= Game.friction;
            } else {
                Hero.xspeed = 0;
            }
        } else if (Hero.xspeed < 0) {
            if (!colliding(Game.friction * -1)) {
                Hero.xspeed += Game.friction;
            } else {
                Hero.xspeed = 0;
            }
        }
    }
    
    if (inArray(Key.UP, Game.keysDown) && !Hero.falling) {
        Hero.jumping = true;
        
        if (Hero.yspeed >= ((Game.maxSpeed * 1.25) * -1)) {
            if (!colliding(0, (Game.increment * -1))) {
                Hero.yspeed -= Game.increment;
            }
        } else {
            Hero.falling = true;
        }
    } else {
        Hero.jumping = false;
    }
    
    if (!Hero.jumping) {
        if (!colliding(0, (Game.increment))) {
            Hero.yspeed += Game.increment;
            Hero.falling = true;
        } else {
            Hero.yspeed = 0;
            Hero.falling = false;
        }
    }
        
    Hero.x += parseInt(Math.floor(Hero.xspeed));
    Hero.y += parseInt(Math.floor(Hero.yspeed));
    
    Hero.container.style.left = Hero.x + "px";
    Hero.container.style.top = Hero.y + "px";
    
    animate();
    
    $('#moves span').text(Grid.changesLeft);
    $('#score span').text(Game.score);

    if (Game.active) {
        setTimeout(function() {
            gameLoop();
        }, 50);
    }
}

function animate() {
    if (Hero.xspeed > 0) {
        if (Hero.jumping || Hero.falling) {
            Hero.container.style.backgroundImage = 'url(/r/easter/img/jump-r.png)';
            Hero.container.style.backgroundPosition = '-5px 0px';
        } else {
            Hero.container.style.backgroundImage = 'url(/r/easter/img/sprite-r.png)';
            Hero.container.style.backgroundPosition = '-5px  -' + (Hero.frameCount * Grid.tileSize) + 'px';

            if (Hero.frameCount == Hero.framesTotal) {
                Hero.frameCount = 0;
            } else {
                Hero.frameCount++;
            }       
        } 
    } else if (Hero.xspeed < 0) {
        if (Hero.jumping || Hero.falling) {
            Hero.container.style.backgroundImage = 'url(/r/easter/img/jump-l.png)';
            Hero.container.style.backgroundPosition = '-5px 0px';
        } else {
            Hero.container.style.backgroundImage = 'url(/r/easter/img/sprite-l.png)';

            Hero.container.style.backgroundPosition = '-5px -' + (Hero.frameCount * Grid.tileSize) + 'px';

            if (Hero.frameCount == Hero.framesTotal) {
                Hero.frameCount = 0;
            } else {
                Hero.frameCount++;
            }
        }
    } else {
        Hero.container.style.backgroundImage = 'url(/r/easter/img/stand.png)';
        Hero.container.style.backgroundPosition = '-5px 0px';
    }
}

function presentFinishPopup() {
    alert("Congratulations! You won the game!");
}

$(document).ready(function() {
    var phr = new Array();
    
    $('#easter-egg').click(function() {
        $('div.holder').html($('div.holder').html() + '<div id="easter-name" style="font-size: 11px; position: absolute;">What\'s my name?</div>');
        $('#easter-name').css('bottom', '10px');
        $('#easter-name').css('right', '30px');
    });
    
    $(document).keydown(function(e) {
       if (Game.active) {
           switch (e.keyCode) {
               case Key.ENTER:
                   if (!Game.started) {
                       var game = document.getElementById('game');
                       Game.started = true;
           
                       var divs = "";
                       divs += '<div id="score">Score: <span>0</span></div>';
                       divs += '<div id="moves">Moves Left: <span>10</span></div>';
                       divs += '<div id="grid"></div>';

                       game.innerHTML = divs;

                       initializeGrid();
                   }
                   break;
               case Key.LEFT:
                    if (!inArray(Key.RIGHT, Game.keysDown) && !inArray(Key.LEFT, Game.keysDown)) {
                        Game.keysDown.push(Key.LEFT);
                    }
                    break;
               case Key.RIGHT:
                    if (!inArray(Key.LEFT, Game.keysDown) && !inArray(Key.RIGHT, Game.keysDown)) {
                        Game.keysDown.push(Key.RIGHT);
                    }
                    break;
                case Key.UP:
                    if (!inArray(Key.UP, Game.keysDown)) {
                        Game.keysDown.push(Key.UP);
                    }
                    break;
           }
       } else {
           phr.push(e.keyCode);
           
           if (phr.length >= 4) {
                if (phr[phr.length - 1] == 79 &&
                    phr[phr.length - 2] == 82 &&
                    phr[phr.length - 3] == 69 &&
                    phr[phr.length - 4] == 72) {
                    Game.active = true;
                    phr = undefined;
                    $('div.holder').html('<div id="game"><div id="intro"></div></div>');
                    $('div.holder').css('padding', '0px');
                    $('div.holder').css('width', '620px');
                    $('div.holder').css('height', $('#game').height() + 'px');
                }
           }
       }
    });
    
    $(document).keyup(function(e) {
       if (Game.active) {
           switch (e.keyCode) {
               case Key.LEFT:
                    Game.keysDown = removeFromArray(Key.LEFT, Game.keysDown);
                    break;
               case Key.RIGHT:
                    Game.keysDown = removeFromArray(Key.RIGHT, Game.keysDown);
                    break;
                case Key.UP:
                    Game.keysDown = removeFromArray(Key.UP, Game.keysDown);
                    break;
           }
       }
    });
    
    $(this).bind("contextmenu", function(e) {
        e.preventDefault();
    });
    
    $('#grid div').live('mousedown', function(e) {
        if (Grid.changesLeft > 0 && Game.active) {
            
            if (!$(this).hasClass('start') && 
                !$(this).hasClass('finish') &&
                !$(this).hasClass('diamond') &&
                ($(this).attr('id') != 'hero')) {
                    
                switch(e.which) {
                    case 1: // Left click
                        if (!$(this).hasClass('block1') &&
                            !$(this).hasClass('block2') &&
                            !$(this).hasClass('block3') &&
                            !$(this).hasClass('block4') &&
                            !$(this).hasClass('block5')) {
                            
                            do {
                                blockType = Math.floor(Math.random() * 7) - 1;
                            } while(blockType == 0);
                            
                            $(this).addClass('block' + blockType);
                            
                            var left = $(this).css('left');
                            left = parseInt(left.substr(0, left.length - 2));
                            
                            var top = $(this).css('top');
                            top = parseInt(top.substr(0, top.length - 2));
                            
                            var x = Math.floor(left / Grid.tileSize);
                            var y = Math.floor(top / Grid.tileSize);
                            Grid.data[x][y] = TileType.WALL;
                        }
                        break;
                    case 3: // Right click
                        for (var i = 1; i < 7; i++) {
                            if ($(this).hasClass('block' + i)) {
                                $(this).removeClass('block' + i);
                                
                                var left = $(this).css('left');
                                left = parseInt(left.substr(0, left.length - 2));

                                var top = $(this).css('top');
                                top = parseInt(top.substr(0, top.length - 2));

                                var x = Math.floor(left / Grid.tileSize);
                                var y = Math.floor(top / Grid.tileSize);
                                Grid.data[x][y] = TileType.EMPTY;
                            }
                        }
                        break;
                }
                
                Grid.changesLeft--;
                
            }
        }
    });
});
