#include "main.h"


tetromino playfield[FULL_HEIGHT][FULL_WIDTH] = {};


int main () {
  

  /* Setting up the seed */
  
  srand(time(NULL));


  /* Setting up terminal with termios */
  
  struct termios old, new;

  tcgetattr(STDIN_FILENO, &old);
  new = old;

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

  tcsetattr(STDIN_FILENO, TCSANOW, &new);

  struct winsize init_size, current_size;
  ioctl(STDOUT_FILENO, TIOCGWINSZ, &init_size);
  current_size = init_size;

  printf("\033[?25l\033[?1049h");


  /* Init */

  init_field();

  bool is_piece = false;

  piece current_piece = {};


  uint16_t i;

  for (i = 0;; i++) {

    int8_t move = 0;
    bool down = false;
    bool draw = false;
    bool rotate = false;

    int8_t j, k;

    if (!is_piece) {
      current_piece = init_piece((rand() % Z_PIECE) + 1);
      is_piece = true;
      draw = true;
      i = 0;
    }


    /* Take care of the input */


    char buf[10] = {};

    if (read(STDIN_FILENO, buf, sizeof(buf)) > 0) {
      if (buf[0] == 'q') {
        break;
      }

      if (buf[0] == '\033' && buf[1] == '[') {
        
        switch (buf[2]) {
          case 'A':
            rotate = true;
            break;
          case 'B':
            down = true;
            break;
          case 'C':
            move = 1;
            break;
          case 'D':
            move = -1;
            break;
          default:
            break;
        }
      }
    }


    /* Move piece */

    if (move != 0) {
      if (
        current_piece.x + move >= 0 && 
        current_piece.x + move + current_piece.size <= FULL_WIDTH
      ) {
       
        bool is_valid = true;

        piece moved_piece = current_piece;
        moved_piece.x += move;

        if (valid_position(moved_piece)) {
          current_piece.x += move;
          draw = true;
        }
      }
    }


    /* Piece rotates */
    
    if (rotate && current_piece.positions > 1) {
      
      piece rotated = current_piece;

      rotated.rotation = (current_piece.rotation + 1) % (current_piece.positions);
      
      if (valid_position(rotated)) {
        current_piece = rotated;
        draw = true;
      }
    }
    

    /* Piece falls */

    if (i >= 100 || down) {
      current_piece.y++;
      i = 0;
      draw = true;
    }


    /* When a piece is stuck */

    if (!valid_position(current_piece)) {

      for (j = 0; j < current_piece.size; j++) {
        for (k = 0; k < current_piece.size; k++) {
          
          if (current_piece.piece[j][k]) {
            
            coord solid = find_direction(current_piece, k, j);

            playfield[current_piece.y - 1 + solid.y][current_piece.x + solid.x] = current_piece.name;
          }
        }
      }
      is_piece = false;
      draw = true;
    }


    /* Looks if there is a tetris */

    bool blink[FIELD_HEIGHT] = {};
    bool is_tetris = false;

    for (j = FIELD_HEIGHT - 1; j >= 0; j--) {

      uint8_t blocked = 0;

      for (k = 0; k < FIELD_WIDTH; k++) {
        if (playfield[j][k + BORDER_WIDTH] != EMPTY)
          blocked++;
      }

      if (blocked == 10) {
        
        blink[j] = true;
        is_tetris = true;  
      }
    }

    if (is_tetris) {
      for (j = 0; j < 4; j++) {
        draw_board(current_piece, (j % 2 == 0) ? NULL : blink, is_piece);
        usleep(200000);
      }

      for (j = 0; j < FIELD_HEIGHT; j++) {
        if (blink[j]) {

          for (k = j; k > 0; k--) {
            int8_t l;
          
            for (l = 0; l < FIELD_WIDTH; l++) {
              playfield[k][l + BORDER_WIDTH] = playfield[k - 1][l + BORDER_WIDTH];
            }
          }
        }
      }
    }


    /* Looks for game over */

    for (j = 0; j < FIELD_WIDTH; j++) {
      if (playfield[TOP_GAP][j + BORDER_WIDTH] > 0) {
        draw_board(current_piece, NULL, is_piece);
        sleep(2);
        printf("\033[2J\033[H");
        printf("HAHA LOSER\n");
        sleep(1);
        goto end;
      }
    }


    if (draw)
      draw_board(current_piece, NULL, is_piece);
    usleep(10000);
  }

end:

  printf("\033[?1049l\033[?25h");

  tcsetattr(STDIN_FILENO, TCSANOW, &old);

  return 0;
}
