/**
 *   \file utilities.h
 *   \brief Déclaraction des structures de données et fonctions utilitaires.
 *
 *  Dans ce fichier sont déclarées et implémentées les structures qui serviront
 *  de conteneurs aux données manipulées. Sont également déclarées les fonctions
 *  utilitaires pour la manipulation de ces structures.
 */

#ifndef UTILITIES_H
#define UTILITIES_H

#include "darray.h"
/* #include <GL/gl.h> */
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

/*****************************************************************************/
/*                             DEFINE DIRECTIVES                             */
/*****************************************************************************/

#ifdef Debug
#define DEBUG if (1)
#define PDEB                                                                   \
  if (1)                                                                       \
  printf
#else
#define DEBUG if (0)
#define PDBEF                                                                  \
  if (0)                                                                       \
  printf
#endif

/*****************************************************************************/
/*                             STRUCT DECLARATION                            */
/*****************************************************************************/

struct Image;
typedef struct Image Image;
struct Pixel;
typedef struct Pixel Pixel;
struct Zone;
typedef struct Zone Zone;
struct Segment;
typedef struct Segment Segment;

/*****************************************************************************/
/*                           STRUCT IMPLEMENTATION                           */
/*****************************************************************************/

/**
 *  \brief Conteneur d’une image
 *
 *  Une image est une structure définie par ses dimensions verticales et
 *  horizontales x et y, et contenant pour chacune des coordonnées possibles
 *  selon ses dimensions un pixel de type \ref Pixel. Ces pixels sont stockés
 *  dans un tableau dynamique \ref darray.
 */
struct Image {
  uint64_t x;      /*!< Largeur de l’image */
  uint64_t y;      /*!< Hauteur de l’image */
  darray *pixels;  /*!< Vecteur à une dimention de pixels */
};

/**
 *  \brief Conteneur d’un pixel
 *
 *  Un pixel est défini par sa couleur représenté en RGB (rouge, vert, bleu).
 *  Il contient également une valeur booléenne afin de savoir si le Pixel fut
 *  visité précédemment par l’algorithme de compression.
 */
struct Pixel {
  uint8_t r;    /*!< Couleur rouge du pixel */
  uint8_t g;    /*!< Couleur verte du pixel */
  uint8_t b;    /*!< Couleur bleue du pixel */
  bool visited; /*!< Le pixel a-t-il été visité avant */
};

/**
 *  \brief Conteneur de zone de couleur unie
 *
 *  Une zone est un ensemble de pixels de même couleur ou de couleur similaire
 *  dont on conserve uniquement les marges dans le tableau dynamique.
 */
struct Zone {
  uint8_t r;          /*!< Couleur rouge de la zone */
  uint8_t g;          /*!< Couleur verte de la zone */
  uint8_t b;          /*!< Couleur bleue de la zone */
  darray *segments;   /*!< Vecteur de segments */
};

/**
 *  \brief Conteneur de segment de couleur unie
 *
 *  Un segment est un ensemble de pixels de même ordonnée et de couleur unie ou
 *  similaire. Il se définit par son ordonnée y et de ses deux pixels de bordure
 *  à son extrême droite et à son extrême gauche.
 */
struct Segment {
  uint16_t xd; /*!< extrême droit du segment */
  uint16_t xg; /*!< extrême gauche du segment  */
};

/*****************************************************************************/
/*                       Utility functions declaration                       */
/*****************************************************************************/

/// \brief Création d’un nouveau pixel
Pixel *newPixel(uint8_t t_r, uint8_t t_g, uint8_t t_b);
/// \brief Destruction d’un pointeur de pixel
void deletePixel(Pixel *t_self);
/// \brief Création d’une nouvelle image
Image *newImage();
/// \brief Destructeur d’une image
void deleteImage(Image *t_self);
/// \brief Constructeur d’un segment de couleur unie
Segment *newSegment(uint16_t t_xd, uint16_t t_xg);
/// \brief Destructeur d’un segment de couleur unie
void deleteSegment(Segment *t_self);
/// \brief Constructeur de conteneur de zone
Zone* newZone(uint8_t t_r, uint8_t t_g, uint8_t t_b);
/// \brief Destructeur de conteneur de zone
void deleteZone(Zone *t_self);
/// \brief Renvoie un pixel aux coordonnées `(x, y)` dans une image
Pixel *imgAt(Image *t_img, int t_x, int t_y);

#endif /* UTILITIES_H */
