/* Elliott's Snake, version 2 */
// TODO: Make generation of snake automatic

// Compass bearings for directions
UP = 0;
RIGHT = 90;
DOWN = 180;
LEFT = 270;


/* Fruit object */

Fruit = function(x, y, element, width) {
  this.init(x, y, element, width)
}
$.extend(Fruit.prototype, {
  position_x: 0,
  position_y: 0,
  element: 0,
  width: 0,
  
  init: function(x, y, element, width){
    this.position_x = x;
    this.position_y = y;
    this.element = element;
    this.width = width;
  },
  
  place: function(){
    var left = Math.floor(Math.random() * $(window).width() - this.width);
    left -= (left%this.width);

    var top = Math.floor(Math.random() * $(window).height()) - this.width;
    top -= (top%this.width);
    
    if (top > 0){
      top -= this.width;
    }
    
    this.position_x = left;
    this.position_y = top;
    
    this.element.css({'top' : top, 'left' : left});
  }
});


/* A snake */

Snake = function(name, head, up, down, left, right, starting_x, starting_y, fruit) {
  this.init(name, head, up, down, left, right, starting_x, starting_y, fruit);
}

$.extend(Snake.prototype, {
  head: false,
  tail: false,
  width: 20,
  position_x: $(window).width()-this.width,
  position_y: 0,
  screen_width: false,
  screen_height: false,
  timeout: 100,
  direction: DOWN,
  snake_name: 'snake',
  fruit: false,
  self: this,
  automatic: false,
  
  init: function(name, head, up, down, left, right, starting_x, starting_y, fruit){
    this.position_x = starting_x;
    this.position_y = starting_y;
    this.doSizes();
    this.snake_name = name;         // This is used for Sizzle awesomeness
    this.head = head;
    this.head.css('width', '20');   // Probably shouldnt' be hard coded. TODO.
    this.head.css('height', '20');  // See above and TODO.
    
    this.up_key = up;
    this.down_key = down;
    this.right_key = right;
    this.left_key = left;
    
    this.fruit = fruit;
    
    this.move();
    
    var self = this;
    
    setTimeout(function(){if(!self.automatic){self.automatic = true}}, 2000)
    
    $(window).bind('resize', function(){
      self.doSizes();
      self.resetFruit();
    })
    $(document).keydown(function(e){
      var code = (e.keyCode ? e.keyCode : e.which);
      self.getDirectionFrom(code);
    });
  },
  
  addTail: function(){
    h = this.head.clone();
    h.attr('id', this.position_x+'x'+this.position_y);
    h.addClass('block tail '+this.snake_name);
    h.css('left', this.position_x).css('top', this.position_y);
    // This has to be Before instead of After. Don't ask me why, because I can't remember.
    h.insertBefore($(this.head));
  },
  
  // Have they lost!?!?!?!
  hasLost: function(){
    element = '#'+this.position_x+'x'+this.position_y
    if ($(element).length > 0){
      return true;
    }else{
      return false;
    }
  },
  
  getDirectionFrom: function(input){
    
    switch(input){
      case this.up_key:
        if (this.direction != DOWN)   {this.automatic = false; this.direction = UP;    }  break;
      case this.right_key:                                                                      
        if (this.direction != LEFT)   {this.automatic = false; this.direction = RIGHT; }  break;
      case this.down_key:                                                                       
        if (this.direction != UP)     {this.automatic = false; this.direction = DOWN;  }  break;
      case this.left_key:                                                                       
        if (this.direction != RIGHT)  {this.automatic = false; this.direction = LEFT;  }  break;
    }
  },
  
  move: function(){

      if (this.automatic == true){
        if (this.fruit.position_x < this.position_x){ this.direction = LEFT}
        else if (this.fruit.position_x >  this.position_x){ this.direction = RIGHT}
        else if (this.fruit.position_x == this.position_x && this.fruit.position_y <= this.position_y){ this.direction = UP}
        else if (this.fruit.position_x == this.position_x && this.fruit.position_x >=  this.position_y){this.direction = DOWN}
      }

    switch(this.direction){
      case UP:    this.position_y -= this.width; break;
      case RIGHT: this.position_x += this.width; break;
      case DOWN:  this.position_y += this.width; break;
      case LEFT:  this.position_x -= this.width; break;
    }

    if (this.position_y < 0){                               // Off the top
      this.position_y =  (this.screen_height - this.width); 
      this.position_y -= (this.screen_height % this.width); // remainder if there is one
    }
    if (this.position_x < 0){                               // Off the left
      this.position_x =  (this.screen_width - this.width);
      this.position_x -= (this.screen_width % this.width);  // remainder if there is one
    }
    if (this.position_x > (this.screen_width - this.width))  // Off the right
      this.position_x = 0;

    if (this.position_y >= (this.screen_height - this.width)) // Off the bottom
      this.position_y = 0;




    if (this.hasLost()){
      // A collision! Set the timeout to 1000 before their next move.
      this.timeout = 1000;
      this.direction = DOWN;
      var self = this;
      // Reset everything after 1 second
      setTimeout(function(){
        $('.tail.'+self.snake_name).remove();
        x = ($(window).width())-self.width;
        self.position_x = (x - x%self.width);
        
        self.position_y = 0;
        self.timeout = 100;
      }, 1000);
    }
    
    
    
    // Do the actual moving
    this.head.css('left', this.position_x);
    this.head.css('top', this.position_y);
    
    // Remove the last tail, unless they've eaten a fruit.
    if (this.eatingFruit()){
      this.resetFruit();
      this.timeout -= 2;
    }else{
      
      

      
      tail = $('.tail.'+this.snake_name);
      if (tail.length > 1){
        $(tail[0]).remove();
      }
    }
    
    // Set up the next loop too
    var self = this;
    setTimeout(function(){self.move();},this.timeout);
    this.addTail();
  },
  
  doSizes: function(){
    this.screen_width = $(window).width();
    this.screen_height = $(window).height();
    this.screen_width -= (this.screen_width % this.width);
    this.screen_height -= (this.screen_width % this.width);
    // WTF. Removed this.
    // if (this.position_x == 0){this.position_x = this.screen_width - this.width};
  },
  
  resetFruit: function(){
    this.fruit.place();
  },
  
  eatingFruit: function(){
    fruit_x = this.fruit.position_x;
    fruit_y = this.fruit.position_y;
    if (fruit_x == 0)
      return true;
    if (this.position_x == fruit_x && this.position_y == fruit_y)
      return true;
  }
  
});




$(document).ready(function(){
  
  // Fruit object
  fruit = new Fruit(0, 0, $('#fruit'), 20);
  
  // Arrow keys
  s = new Snake('one', $('#head'),38,40,37,39, 0, 0, fruit);

  // Konami Code Mode for two-player
  var kkeys = [], konami = "38,38,40,40,37,39,37,39,66,65";
  $(document).keydown(function(e) {
    kkeys.push( e.keyCode );
    if ( kkeys.toString().indexOf( konami ) >= 0 ){
      $(document).unbind('keydown',arguments.callee); // That's sexy.
      x = ($(window).width()) - this.width%($(window).width()) ;
      s2 = new Snake('two', $('#head_two'),87,83,65,68, x, 0, fruit);
      s2.automatic = false;
    }
  });
  
  fruit.place();

})
