/**
 * Subordinate - Browser-based puzzle game
 * Created by Christopher Carsey and Jacob Smith
 * Uses the Phaser game engine, jQuery, and Bootstrap
 */
var CELL = {
  WIDTH: 100,
  HEIGHT: 100
};

var DIRECTIONS = {
  RIGHT: 0,
  DOWN: 90,
  LEFT: 180,
  UP: 270
};

var SPRITE_MAP = {
  right: 0,
  down: 1,
  up: 2,
  left: 3,
  wall: 4,
  empty: 5,
  carFinish: 6,
  unlockedPawnFinish: 7,
  pawnFinish: 8
};

var game = new Phaser.Game(1, 1, Phaser.AUTO, 'subordinate', {
  preload: preload,
  create: create
});

var grid,
  car,
  puzzle,
  currentRow,
  currentCol,
  currentCarRow,
  currentCarCol,
  pawn,
  sprites,
  pawnFinish,
  moveCount = 0,
  highScore,
  gameNumber;

function preload() {
  game.load.image('car', 'assets/car.png');
  game.load.image('pawn', 'assets/pawn.png');
  game.load.image('grid', 'assets/grid.png');
  game.load.spritesheet('ms', 'assets/arrowSprite.png', 100, 100);
  gameNumber = getParameterByName('game') || 1;
  game.load.json('puzzle', 'assets/puzzles/' + gameNumber + '.json');
  $('#puzzle' + gameNumber).addClass('active');
  highScore = Cookies.get('highScore' + gameNumber) || 'None';
}

function create() {
  $('#highScore').html(highScore);
  puzzle = game.cache.getJSON('puzzle');
  game.scale.setGameSize(CELL.WIDTH * puzzle.cells[0].length, CELL.HEIGHT * puzzle.cells.length);
  game.stage.backgroundColor = '#ffffff';

  grid = game.add.tileSprite(0, 0, CELL.WIDTH * puzzle.cells[0].length, CELL.HEIGHT * puzzle.cells.length, 'grid');
  sprites = [];
  $.each(puzzle.cells, function(rowIndex, row) {
    sprites[rowIndex] = [];
    $.each(row, function(colIndex, col) {
      sprites[rowIndex][colIndex] = game.add.sprite(CELL.WIDTH * colIndex, CELL.HEIGHT * rowIndex, 'ms');
      sprites[rowIndex][colIndex].frame = SPRITE_MAP[col];
      if (col === 'pawnFinish') {
        pawnFinish = {
          row: rowIndex,
          col: colIndex
        };
      }
    });
  });

  currentRow = puzzle.start.pawn.row;
  currentCol = puzzle.start.pawn.col;
  pawn = game.add.sprite(CELL.WIDTH * currentCol, CELL.HEIGHT * currentRow, 'pawn');
  currentCarRow = puzzle.start.car.row;
  currentCarCol = puzzle.start.car.col;
  car = game.add.sprite(CELL.WIDTH * currentCarCol, CELL.HEIGHT * currentCarRow, 'car');
  game.input.keyboard.addCallbacks(null, move);
}

function move(event) {
  event.preventDefault();
  switch (event.keyCode) {
    case Phaser.KeyCode.UP:
    case Phaser.KeyCode.W:
      moveTo(currentRow - 1, currentCol);
      break;
    case Phaser.KeyCode.DOWN:
    case Phaser.KeyCode.S:
      moveTo(currentRow + 1, currentCol);
      break;
    case Phaser.KeyCode.LEFT:
    case Phaser.KeyCode.A:
      moveTo(currentRow, currentCol - 1);
      break;
    case Phaser.KeyCode.RIGHT:
    case Phaser.KeyCode.D:
      moveTo(currentRow, currentCol + 1);
      break;
  }
}

function moveTo(row, col, item) {
  if (canMoveTo(row, col)) {
    moveCount++;
    $('#moveCount').html(moveCount);
    currentRow = row;
    currentCol = col;
    pawn.position.y = currentRow * CELL.HEIGHT;
    pawn.position.x = currentCol * CELL.WIDTH;

    // Move car if possible
    var newCarRow, newCarCol;
    switch (puzzle.cells[row][col]) {
      case 'up':
        newCarRow = currentCarRow - 1;
        newCarCol = currentCarCol;
        break;
      case 'down':
        newCarRow = currentCarRow + 1;
        newCarCol = currentCarCol;
        break;
      case 'left':
        newCarRow = currentCarRow;
        newCarCol = currentCarCol - 1;
        break;
      case 'right':
        newCarRow = currentCarRow;
        newCarCol = currentCarCol + 1;
        break;
    }

    if (canMoveTo(newCarRow, newCarCol, true)) {
      currentCarRow = newCarRow;
      currentCarCol = newCarCol;
      car.position.y = currentCarRow * CELL.HEIGHT;
      car.position.x = currentCarCol * CELL.WIDTH;

      if (puzzle.cells[currentCarRow][currentCarCol] === 'carFinish') {
        sprites[pawnFinish.row][pawnFinish.col].frame = SPRITE_MAP.unlockedPawnFinish;
      } else {
        sprites[pawnFinish.row][pawnFinish.col].frame = SPRITE_MAP.pawnFinish;
      }
    }

    // Win condition
    if (puzzle.cells[currentRow][currentCol] === 'pawnFinish') {
      $('#win').show();
      if (highScore === 'None' || highScore > moveCount) {
        highScore = moveCount;
        Cookies.set('highScore' + gameNumber, highScore);
        $('#highScore').html(highScore);
      }
    }
  }
}

function canMoveTo(row, col, isCar) {
  var rowInBounds = row > -1 && row < puzzle.cells.length;
  var colInBounds = col > -1 && col < puzzle.cells[0].length;
  if (rowInBounds && colInBounds) {
    var pawnIsThere = isCar && row === currentRow && col === currentCol;
    var carIsThere = !isCar && row === currentCarRow && col === currentCarCol;
    if (pawnIsThere || carIsThere) {
      return false;
    }
    if (puzzle.cells[row][col] === 'wall') {
      return false;
    }
    var goingToPawnFinish = puzzle.cells[row][col] === 'pawnFinish';
    var carInFinish = puzzle.cells[currentCarRow][currentCarCol] === 'carFinish';
    if (!isCar && goingToPawnFinish && !carInFinish) {
      return false;
    }
    return true;
  }
  return false;
}

// Handle the restart button (jQuery feels ugly)
$('#restart').click(function() {
  location.href = '?game=' + gameNumber;
});

function getParameterByName(name, url) {
  if (!url) url = window.location.href;
  name = name.replace(/[\[\]]/g, '\\$&');
  var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
    results = regex.exec(url);
  if (!results) return null;
  if (!results[2]) return '';
  return decodeURIComponent(results[2].replace(/\+/g, ' '));
}