#include "snake.h"



uint8_t update_snake (selected game_size, snake *my_snake, direction shift) {
  
  my_snake->position[0].directions[1] = my_snake->position[0].directions[0];
  my_snake->position[0].directions[0] = shift;

  uint16_t i;
  for (i = my_snake->length; i > 0; i--)
    my_snake->position[i] = my_snake->position[i - 1];

  switch (shift) {
  case UP:
    my_snake->position[0].coords.y =
        ((my_snake->position[0].coords.y + game_size.y - 1) % game_size.y);
    break;
  case DOWN:
    my_snake->position[0].coords.y = ((my_snake->position[0].coords.y + 1) % game_size.y);
    break;
  case LEFT:
    my_snake->position[0].coords.x =((my_snake->position[0].coords.x + game_size.x - 1) % game_size.x);
    break;
  case RIGHT:
    my_snake->position[0].coords.x = ((my_snake->position[0].coords.x + 1) % game_size.x);
    break;
  default:
    return 0;
    break;
  }

  uint8_t head_y = my_snake->position[0].coords.y;
  uint8_t head_x = my_snake->position[0].coords.x;

  for (i = 1; i < my_snake->length; i++) {
    int16_t x = my_snake->position[i].coords.x;
    int16_t y = my_snake->position[i].coords.y;

    if (x == head_x && y == head_y)
      return 2;
  }


  return 1;
}

void update_field(snake my_snake, selected game_size, board_state **board, bool init) {

  uint8_t i, j;

  board_state snake_bit[DIRECTIONS][DIRECTIONS] = {
    [UP][UP] = VERTICAL,
    [DOWN][DOWN] = VERTICAL,
    
    [RIGHT][RIGHT] = HORIZONTAL,
    [LEFT][LEFT] = HORIZONTAL,
    
    [DOWN][RIGHT] = BOTTOM_LEFT,
    [LEFT][UP] = BOTTOM_LEFT,
    
    [UP][RIGHT] = TOP_LEFT,
    [LEFT][DOWN] = TOP_LEFT,
    
    [DOWN][LEFT] = BOTTOM_RIGHT,
    [RIGHT][UP] = BOTTOM_RIGHT,
          
    [UP][LEFT] = TOP_RIGHT,
    [RIGHT][DOWN] = TOP_RIGHT
  };


  if (init) {
    for (i = 0; i < game_size.y; i++) {
      for (j = 0; j < game_size.x; j++) {
        board[i][j] = AIR;
      }
    }

    for (i = 1; i < my_snake.length; i++) {
      int16_t x = my_snake.position[i].coords.x;
      int16_t y = my_snake.position[i].coords.y;
      
      if (x >= 0 && y >= 0) {

        direction first = my_snake.position[i].directions[0];
        direction second = my_snake.position[i].directions[1];

        board[y][x] = snake_bit[first][second];
      }
    }
  } else {
    
    int16_t x = my_snake.position[my_snake.length].coords.x;
    int16_t y = my_snake.position[my_snake.length].coords.y;
    
    if (x != -1 && y != -1)
      board[y][x] = AIR;

    
    x = my_snake.position[1].coords.x;
    y = my_snake.position[1].coords.y;
  
    direction first = my_snake.position[1].directions[0];
    direction second = my_snake.position[1].directions[1];
    
    if (x != -1 && y != -1)
      board[y][x] = snake_bit[first][second];
  }


  int16_t x = my_snake.position[0].coords.x;
  int16_t y = my_snake.position[0].coords.y;

  if (my_snake.position[0].directions[0] == RIGHT) {
    board[y][x] = HEAD_1;
  } else {
    board[y][x] = HEAD_2;
  }

  for (i = 0; i < game_size.y; i++) {
    for (j = 0; j < game_size.x; j++) {
      if (board[i][j] == FRUIT)
        return;
    }
  } 
  
  while (true) {
    x = rand() % game_size.x;
    y = rand() % game_size.y;

    if (board[y][x] == AIR) {
      board[y][x] = FRUIT;
      return;
    }
  } 
}

direction read_direction(char *string, bool wasd_enabled) {

  if (string[0] == '\033') {

    if (strlen(string) == 1)
      return ESCAPE;

    if (strlen(string) >= 3) {

      if (string[1] == '[') {

        switch (string[2]) {
        case RIGHT_CODE:
          return RIGHT;
          break;
        case LEFT_CODE:
          return LEFT;
          break;
        case UP_CODE:
          return UP;
          break;
        case DOWN_CODE:
          return DOWN;
          break;
        }
      }
    }
  }

  if (wasd_enabled) {
    switch (toupper(string[0])) {
    case 'A':
      return LEFT;
      break;
    case 'D':
      return RIGHT;
      break;
    case 'W':
      return UP;
      break;
    case 'S':
      return DOWN;
      break;
    }
  }

  switch (toupper(string[0])) {
    case 'Q':
      return Q_BUTTON;
      break;
    case 'P':
      return P_BUTTON;
      break;
    case '\n':
      return ENTER;
      break;
    case 127:
      return DEL;
    default:
      return DIRECTIONS;
      break;
  }
}
