/**
 * Super Tapper JavaScript
 * 
 * @author David Miles
 * @created 11/27/2010
 * @revised 11/28/2010
 */
 
/**
 * Console fix
 */
if(console === undefined){
  var console = {log: function(msg){ alert("Console: " + msg); }};
}
 
/**
 * Page load event
 */
window.onload = function(){
  document.getElementById("game").appendChild(new SuperTapper.Game());
};
 
// Namespace SuperTapper {{{
var SuperTapper = {};
 
/**
 * SuperTapper Game class
 */
SuperTapper.Game = function(){
  // Difficulties
  this.difficulty = null;
  this.difficulties = ["Easy", "Hard", "Disco"];
 
  // Screens
  this.title = null;
  this.game = null;
 
  // Game variables
  this.gameTimer = null;
  this.gameInterval = null;
  this.gameEnemy = null;
  this.gamePlayer = null;
  this.gameScore = null;
  this.score = null;
 
  // Disco moe
  this.discoTImer = null;
 
  // Initialize title screen
  this.initTitle();
 
  this.screen = document.createElement("div");
  this.screen.appendChild(this.title);
  return this.screen;
};
SuperTapper.Game.prototype.initTitle = function(){
  // Keep a self reference for closures
  var self = this;
 
  // Title container
  this.title = document.createElement("div");
  this.title.setAttribute("id", "gameTitle");
  this.title.setAttribute("class", "round");
 
  // Header
  var header = document.createElement("h1");
 
  // @TODO: Add player name for high scores
 
  // Difficulties
  var difficulty = document.createElement("div");
  difficulty.setAttribute("id", "gameDifficulty");
 
  for(var i in this.difficulties){
    // Container
    var div = document.createElement("div");
    div.setAttribute("class", "difficulty");
 
    // Radio button
    var radio = document.createElement("input");
    radio.setAttribute("id", "difficulty" + this.difficulties[i]);
    radio.setAttribute("type", "radio");
    radio.setAttribute("name", "difficulty");
    radio.setAttribute("value", i);
    radio.onclick = function(){
      self.difficulty = parseInt(this.value);
    };
 
    // Label
    var label = document.createElement("label");
    label.setAttribute("for", "difficulty" + this.difficulties[i]);
    label.innerText = this.difficulties[i];
 
    // Append
    div.appendChild(radio);
    div.appendChild(label);
    difficulty.appendChild(div);
  }
 
  // Start button
  var start = document.createElement("a");
  start.setAttribute("id", "startGame");
  start.setAttribute("href", "#");
 
  // Start button onClick event
  start.onclick = function(){
    if(self.difficulty !== null){
      self.start();
    }else{
      alert("You must select a difficulty!");
    }
    return false;
  };
 
  // Append all children to the title
  this.title.appendChild(header);
  this.title.appendChild(difficulty);
  this.title.appendChild(start);
};
SuperTapper.Game.prototype.initGame = function(){
  // Keep a self reference for closures
  var self = this;
 
  // Game container
  this.game = document.createElement("div");
  this.game.setAttribute("id", "gamePlaying");
  this.game.setAttribute("class", "round");
 
  // Game objects
  this.gamePlayer = new SuperTapper.Player();
  this.gameEnemy = new SuperTapper.Enemy();
  this.gameScore = document.createElement("div");
  this.gameScore.setAttribute("id", "score");
  this.score = new SuperTapper.Score(this.difficulty);
 
  // Game events
  this.game.onclick = function(){
    self.score.miss();
 
    // We have this call in only this.game.onclick because this event will always
    // fire when clicking on any game objects.
    self.move();
  }
  this.gamePlayer.onclick = function(){
    // Force focus onto the game board (otherwise cheating is possible in IE)
    self.game.focus();
 
    // Register a hit
    self.score.hit(this);
 
    // Compensate for score loss
    self.score.compensate();
    return false;
  }
  this.gameEnemy.onclick = function(){
    // Force focus onto the game board (otherwise cheating is possible in IE)
    self.game.focus();
 
    // Register a hit
    self.score.hit(this);
 
    // Compensate for score loss
    self.score.compensate();
    return false;
  }
 
  // Stop button
  var stop = document.createElement("a");
  stop.setAttribute("id", "stopButton");
  stop.setAttribute("href", "#");
  stop.onclick = function(){
    self.stop();
  };
 
  // Append all elements
  this.game.appendChild(this.gameScore);
  this.game.appendChild(this.gamePlayer);
  this.game.appendChild(this.gameEnemy);
  this.game.appendChild(stop);
 
  // Game movement interval
  switch(this.difficulty){
    case 0:
      this.gameInterval = 1500;
      break;
    case 1:
      this.gameInterval = 1000;
      break;
    case 2:
      this.gameInterval = 750;
 
      // Start disco mode timer
      this.discoTimer = setInterval(function(){
        self.game.style.backgroundColor = "rgb(" + Math.rand(255) + ", " + Math.rand(255) + ", " + Math.rand(255) + ")";
      }, 150);
      break;
  }
 
  // We have to use a separate event handler because self.move() loses the reference
  // to the score object for some reason. So, in this event handler we just call
  // self.move() to move the pieces and then update the score ourself
  var gameTimerTick = function(){
    self.move();
    clearTimeout(self.gameTimer);
    self.gameTimer = setTimeout(arguments.callee, self.gameInterval);
  };
 
  // Start game timer
  this.gameTimer = setTimeout(gameTimerTick, this.gameInterval);
};
SuperTapper.Game.prototype.move = function(){
    var g = this.game;
    var p = this.gamePlayer;
    var e = this.gameEnemy;
 
    // Move player
    p.style.top = Math.rand(g.offsetHeight - p.offsetHeight) + "px";
    p.style.left = Math.rand(g.offsetWidth - p.offsetWidth) + "px";
 
    // Move enemy
    e.style.top = Math.rand(g.offsetHeight - e.offsetHeight) + "px";
    e.style.left = Math.rand(g.offsetWidth - e.offsetWidth) + "px";
 
    // Update score
    this.updateScore();
};
SuperTapper.Game.prototype.updateScore = function(){
  this.gameScore.innerText = this.score.getScore();
};
SuperTapper.Game.prototype.start = function(){
  this.initGame();
  this.screen.removeChild(this.title);
  this.screen.appendChild(this.game);
  this.move();
};
SuperTapper.Game.prototype.stop = function(){
  // Make sure they want to end the game
  if(!confirm("Are you sure you want to end the game?")){
    // Compensate for score loss
    this.score.compensate();
    return false;
  }
  clearTimeout(this.gameTimer);
  if(this.discoTimer !== null){
    clearInterval(this.discoTimer);
  }
  this.screen.removeChild(this.game);
  this.screen.appendChild(this.title);
  alert("You finished with a score of " + this.score.getScore() + "!");
};
 
/**
 * SuperTapper Score class
 */
SuperTapper.Score = function(difficulty){
  this.difficulty = difficulty;
  this.enemyHits = 0;
  this.playerHits = 0;
  this.misses = 0;
};
SuperTapper.Score.prototype.hit = function(e){
  switch(e.id){
    case "gameEnemy":
      this.enemyHits++;
      break;
    case "gamePlayer":
      this.playerHits++;
      break;
  }
};
SuperTapper.Score.prototype.miss = function(){
  this.misses++;
};
SuperTapper.Score.prototype.compensate = function(){
  this.misses--;
};
SuperTapper.Score.prototype.getScore = function(){
  var d = this.difficulty + 1
    , e = this.enemyHits
    , p = this.playerHits
    , m = this.misses;
  return ((e * d) - (p * d) - m) * (10 * d);
}
 
/**
 * SuperTapper Enemy class
 */
SuperTapper.Enemy = function(){
  var enemy = document.createElement("a");
  enemy.setAttribute("id", "gameEnemy");
  enemy.setAttribute("class", "gameObject");
  enemy.setAttribute("href", "#");
  return enemy;
};
 
/**
 * SuperTapper Player class
 */
SuperTapper.Player = function(){
  var player = document.createElement("a");
  player.setAttribute("id", "gamePlayer");
  player.setAttribute("class", "gameObject");
  player.setAttribute("href", "#");
  return player;
};
// }}}
 
/**
 * Generate a random number in a maximum range
 * 
 * @param int max Maximum number to be returned
 * @return int
 */
Math.rand = function(max){
  return Math.floor(Math.random() * max);
}