/**
 * @jsx React.DOM
 */
var BODY = 1, FOOD = 1;
var KEYS = {left: 37, up: 38, right: 39, down: 40};
var DIRS = {37: true, 38: true, 39: true, 40: true};

var SnakeGame = React.createClass({displayName: 'SnakeGame',
  getInitialState: function() {
    var start = this.props.startIndex || 1;
    var snake = [start], board = []; board[start] = BODY;
    return {
      snake: snake,
      board: board,
      growth: 0,
      paused: true,
      gameOver: false,
      direction: KEYS.down
    }
  },

  componentDidMount: function() {
    this._resume();
  },

  _reset: React.autoBind(function() {
    this.setState(this.getInitialState());
    this._resume();
  }),

  _pause: React.autoBind(function() {
    if (this.state.gameOver || this.state.paused) { return; }
    this.setState({paused: true});
  }),

  _resume: React.autoBind(function() {
    if (this.state.gameOver || !this.state.paused) { return; }
    this.setState({paused: false});
    this.refs.board.getDOMNode().focus();
    this._tick();
  }),

  _tick: React.autoBind(function() {
    if (this.state.paused) { return; }
    var snake = this.state.snake;
    var board = this.state.board;
    var growth = this.state.growth;
    var direction = this.state.direction;

    var numRows = this.props.numRows || 25;
    var numCols = this.props.numCols || 25;
    var head = getNextIndex(snake[0], direction, numRows, numCols);

    if(parseInt(snake.length)>parseInt(window.localStorage.getItem("high_score"))){
      window.localStorage.setItem("high_score",parseInt(snake.length));
      document.getElementById("title_div").innerHTML = '<h3>Welcome to Magnetic\'s snake game!</h3><h1 style="color:green">Highscore: '+window.localStorage.getItem("high_score")+'</h1>';
    }

    if (snake.indexOf(head) != -1) {
      this.setState({gameOver: true});
      return;
    }

    var needsFood = board[head] == FOOD || snake.length == 1;
    if (needsFood) {
      var ii, numCells = numRows * numCols;
      do { ii = Math.floor(Math.random() * numCells); } while (board[ii]);
      board[ii] = FOOD;
    }else {
      board[snake.pop()] = null;
    }

    snake.unshift(head);
    board[head] = BODY;

    if (this._nextDirection) {
      direction = this._nextDirection;
      this._nextDirection = null;
    }



    this.setState({
      snake: snake,
      board: board,
      growth: growth,
      direction: direction
    });

    setTimeout(this._tick, 70);
  }),

  _handleKey: React.autoBind(function(event) {
    var direction = event.nativeEvent.keyCode;
    var difference = Math.abs(this.state.direction - direction);
    // if key is invalid, or the same, or in the opposite direction, ignore it
    if (DIRS[direction] && difference !== 0 && difference !== 2) {
      this._nextDirection = direction;
    }
  }),


  render: function() {
    var cells = [];
    var numRows = this.props.numRows || 25;
    var numCols = this.props.numCols || 25;
    var cellSize = this.props.cellSize || 15;

    for (var row = 0; row < numRows; row++) {
      for (var col = 0; col < numCols; col++) {
        var code = this.state.board[numCols * row + col];
        var type = code == BODY ? 'body' : code == FOOD ? 'food' : 'null';
        cells.push(React.DOM.div( {className:type + '-cell'}, null ));
      }
    }

    return (
      React.DOM.div( {className:"snake-game"}, [
        React.DOM.h1( {className:"snake-score"}, ["Current length: ", this.state.snake.length]),
        React.DOM.div(
          {ref:"board",
          className:'snake-board' + (this.state.gameOver ? ' game-over' : ''),
          tabIndex:0,
          onBlur:this._pause,
          onFocus:this._resume,
          onKeyDown:this._handleKey,
          style:{width: numCols * cellSize, height: numRows * cellSize}}, 
          cells
        ),
        React.DOM.div( {className:"snake-controls"}, [
          this.state.paused ?  React.DOM.button( {onClick:this._resume}, "Resume") : null,
          this.state.gameOver ? React.DOM.button( {onClick:this._reset}, "New Game") : null
        ])
      ])
    );
  }
});


function updateHighScore(snake_length){
  if(parseInt(snake_length)>window.localStorage.getItem("highscore")){
    alert("New highscore!");
    window.localStorage.setItem("highscore",parseInt(snake_length))
  }
}
function getNextIndex(head, direction, numRows, numCols) {
  // translate index into x/y coords to make math easier
  var x = head % numCols;
  var y = Math.floor(head / numCols);

  // move forward one step in the correct direction, wrapping if needed
  switch (direction) {
    case KEYS.up:    y = y <= 0 ? numRows - 1 : y - 1; break;
    case KEYS.down:  y = y >= numRows - 1 ? 0 : y + 1; break;
    case KEYS.left:  x = x <= 0 ? numCols - 1 : x - 1; break;
    case KEYS.right: x = x >= numCols - 1 ? 0 : x + 1; break;
    default: return;
  }

  // translate new x/y coords back into array index
  return (numCols * y) + x;
}

React.renderComponent(SnakeGame(null, null ), document.getElementById("root"));
