#include <unistd.h>

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#include <string.h>

#include <termios.h>

#define RIGHT_CODE 'C'
#define LEFT_CODE 'D'
#define UP_CODE 'A'
#define DOWN_CODE 'B'

#define WIDTH 256
#define HEIGHT 256

typedef enum {
  UP, DOWN, LEFT, RIGHT
} direction;

typedef struct selected {
  uint8_t x;
  uint8_t y;
} selected;


void draw_board(selected square_selected, bool redraw);


int main() {

  struct termios old, new;

  tcgetattr(STDIN_FILENO, &old);

  new = old;

  new.c_lflag &= ~(ECHO | ICANON);
  new.c_cc[VMIN] = 0;
  new.c_cc[VTIME] = 1;

  tcsetattr(STDIN_FILENO, TCSANOW, &new);


  selected square_selected = {0, 0};

  draw_board(square_selected, false);

  bool run = true;

  while (run) {

    char string[1000] = {};
    ssize_t n = read(STDIN_FILENO, string, sizeof(string) - 1);
    

    if (n > 0) {
      string[n] = '\0';

      if (strlen(string) >= 3) {
        if (string[0] == '\033') {
          if (string[1] == '[') {
          
            direction shift;
          
            switch (string[2]) {
              case RIGHT_CODE:
                shift = RIGHT;
                break;
              case LEFT_CODE:
                shift = LEFT;
                break;
              case UP_CODE:
                shift = UP;
                break;
              case DOWN_CODE:
                shift = DOWN;
                break;
            }

            switch (shift) {
              case UP:
                square_selected.y = ((square_selected.y + HEIGHT - 1) % HEIGHT);
                break;
              case DOWN:
                square_selected.y = ((square_selected.y + 1) % HEIGHT);
                break;
              case LEFT:
                square_selected.x = ((square_selected.x + WIDTH - 1) % WIDTH);
                break;
              case RIGHT:
                square_selected.x = ((square_selected.x + 1) % WIDTH);
                break;
            }
            
            draw_board(square_selected, true);
          
          }
        }
      }
      if (strstr(string, "q"))
        run = false;
    }
  }


  tcsetattr(STDIN_FILENO, TCSANOW, &old);

  return 0;
}


void draw_board (selected square_selected, bool redraw) {
  
  uint8_t i, j; 

  if (redraw) {
    for (i = 0; i < HEIGHT; i++)
      printf("\033[A");
    printf("\r");
  }

  for ( i = 0; i < HEIGHT; i++) {
    for (j = 0; j < WIDTH; j++) {
      char character = ' ';

      if (i == square_selected.y && j == square_selected.x) {
        character = 'O';
      }

      printf("\033[32m%5c\033[0m",  character);
    }
    printf("\n");
  }
}
