#include "mr4th/mr4th_base.h"
#include <ncurses.h>

#include "mr4th/mr4th_base.c"

int main(){
  Arena *arena = arena_alloc();
  
  // initializes ncurses
  initscr();
  
  // settings
  noecho();
  cbreak();
  
  B32 animating = 1;
  
  // get size
  U32 window_x = 0;
  U32 window_y = 0;
  getmaxyx(stdscr, window_y, window_x);
  
  U32 window_stride = window_x;
  
  // window buffer
  U32 buffer_size = window_stride*window_y;
  U8 *buffer = push_array(arena, U8, buffer_size);
  
  // cell grid
  U32 grid_x = window_x + 2;
  U32 grid_y = window_y + 2;
  B8 *cell = push_array(arena, B8, grid_x*grid_y);
  B8 *celln = push_array(arena, B8, grid_x*grid_y);
  
  cell[ 7 +  9*grid_x] = 1;
  cell[ 8 +  9*grid_x] = 1;
  cell[11 +  9*grid_x] = 1;
  cell[12 +  9*grid_x] = 1;
  cell[13 +  9*grid_x] = 1;
  cell[10 + 10*grid_x] = 1;
  cell[ 8 + 11*grid_x] = 1;
  
  cell[12 + 13*grid_x] = 1;
  cell[13 + 13*grid_x] = 1;
  cell[16 + 13*grid_x] = 1;
  cell[17 + 13*grid_x] = 1;
  cell[18 + 13*grid_x] = 1;
  cell[15 + 14*grid_x] = 1;
  cell[13 + 15*grid_x] = 1;
  
  // animation
  U32 t = 0;
  for (;;){
    
    // cell -> buffer
    for (U32 y = 0; y < window_y; y += 1){
      for (U32 x = 0; x < window_x; x += 1){
        U8 b = ' ';
        if (cell[(x + 1) + (y + 1)*grid_x]){
          b = '#';
        }
        buffer[x + y*window_stride] = b;
      }
    }
    
    // print
    move(0, 0);
    printw("%.*s", buffer_size, buffer);
    refresh();
    if (animating){
      os_sleep_milliseconds(1000/6);
    }
    else{
      getch();
    }
    
    // iterate
    t += 1;
    for (S32 y = 0; y < window_y; y += 1){
      S32 cy = y + 1;
      for (S32 x = 0; x < window_x; x += 1){
        S32 cx = x + 1;
        
        static S8 neighborhood[] = {
          -1, -1,  0, -1, +1, -1,
          -1,  0,         +1,  0,
          -1, +1,  0, +1, +1, +1,
        };
        
        S32 count = 0;
        for (S32 i = 0; i < ArrayCount(neighborhood); i += 2){
          S32 xi = cx + neighborhood[i];
          S32 yi = cy + neighborhood[i + 1];
          count += cell[xi + yi*grid_x];
        }
        
        B8 n = 0;
        if (cell[cx + cy*grid_x]){
          if (count == 2 || count == 3){
            n = 1;
          }
        }
        else{
          if (count == 3){
            n = 1;
          }
        }
        
        celln[cx + cy*grid_x] = n;
      }
    }
    
    Swap(B8*, cell, celln);
    
  }
  
  return(0);
}
