#ifndef __GOL_H__
#define __GOL_H__

#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>

typedef struct game_s
{
    bool state;
    int neighbor_alive;
} game ;

typedef struct grid_s
{
    int rows;
    int cols;
    float update_rate;
    bool paused;
    game* game;
} grid;

/**
 * @brief The game loop for the terminal version of the game
 **/
void gameLoop(grid* gol);

/**
 * @brief Print the grid for the terminal version of the game.
 **/
void printGrid(grid* gol);

/**
 * @brief Create a new grid and game.
 * @return the created grid
 **/
grid* newGrid(int row, int cols, float alive, float update_rate);

/**
 * @brief Delete the given grid.
 **/
void deleteGrid(grid* gol);

/**
 * @brief Set the neighbor_alive var in game for each cell based on the 8 surronding cell.
 **/
void checkNeighbor(grid* gol);

/**
 * @brief Update each cell based on the number of neighbor and it's initial state based on the rule of the game of life.
 **/
void updateState(grid* gol);

/**
 * @brief Change a specific cell state in the grid.
 **/
void changeState(int x, int y,bool state, grid* gol);

/**
 * @brief Check if the given coordinates exist in the grid.
 * @return if it's in the grid or not in a bool
 **/
bool inGrid(int x, int y, grid* gol);

/**
 * @brief Load a grid based on a given file.
 * @return the loaded game
 **/
grid* load(char* filename);

/**
 * @brief Save the given grid in filename.
 **/
void save(char* filename, grid* gol);

/**
 * @brief get the number of rows in a grid.
 * @return The number of rows.
 **/
int getRows(grid* gol);

/**
 * @brief get the number of cols in a grid.
 * @return The number of cols.
 **/
int getCols(grid* gol);

/**
 * @brief Check if the grid is paused.
 * @return the state of the grid in a bool.
 **/
bool getPause(grid* gol);

/**
 * @brief get the update rate of the grid.
 * @return The update rate in a float.
 **/
float getRate(grid* gol);

/**
 * @brief get the current state of a cell in the grid.
 * @return if the cell alive or dead in a bool.
 **/
bool getState(int x, int y, grid* gol);

/**
 * @brief change the update rate of the grid.
 **/
void setRate(float rate, grid* gol);

/**
 * @brief change if the grid is paused based of the bool.
 **/
void setPause(bool pause, grid* gol);

#endif  // __GOL_H__
