#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>

// Définition des broches pour l'écran TFT
#define TFT_CLK 13
#define TFT_MISO 12
#define TFT_MOSI 11
#define TFT_DC 5
#define TFT_CS 4
#define TFT_RST 8
#define ILI9341_BLACK 0x0000  ///< Couleur noir
#define ILI9341_YELLOW 0xFFE0 ///< Couleur jaune

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

const int SEUIL_ACTION_BAS = 15;
const int SEUIL_ACTION_HAUT = 1000;
const int NB_ZONES = 3; // 3 zones pour chaque dimension (3x3)
const int LCD_COLONNES = 10; // Nombre de "colonnes logiques"
const int LCD_LIGNES = 10; // Nombre de "lignes logiques"
const int PIXELS_PAR_COLONNE = 24; // Largeur d'une "colonne logique" en pixels
const int PIXELS_PAR_LIGNE = 32; // Hauteur d'une "ligne logique" en pixels

// === Définition des graphismes personnalisés ===
const uint8_t persoGraphique[] = 
{
  0b01000010,
  0b01100110,
  0b00011000,
  0b00011000,
  0b01111110,
  0b01011010,
  0b00100100,
  0b01000010
};
const uint8_t buissonGraphique[] = {
    0b00000, 0b01110, 0b11111, 0b11111,
    0b11111, 0b01110, 0b00000, 0b00000
};
const uint8_t clefGraphique[] = {
    0b00110, 0b00100, 0b00110, 0b00100,
    0b00100, 0b01110, 0b01010, 0b01110
};

// === Structures ===
struct Coordonnees {
    int colonne;
    int ligne;
};

struct Zone {
    Coordonnees positionPerso;
    Coordonnees positionClef;
    Coordonnees positionBuissons[5];
    int nbBuissons;
    bool clefPresente;
};

struct Perso {
    Coordonnees position;
    int vitesse;
    unsigned long compteurVitesse;
};

// === Variables globales ===
Zone zones[NB_ZONES][NB_ZONES];
Perso perso = {{0, 0}, 100, 0};
int zoneActuelleX = 1;
int zoneActuelleY = 1;
int J1, J2;
int maxBuisson=10;
// === Données de la carte ===
const int mapBuissons[NB_ZONES][NB_ZONES][9][2] = {
    {   // Zone 0,0  {colonne, ligne}
        {{1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1},
        {6, 1}, {6, 2}, {-1, -1}, {-1, -1}},
    {{1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1},
         {6, 1}, {6, 2}, {-1, -1}, {-1, -1}},
       {{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5},
        {1, 6}, {1, 7}, {1, 8}, {1,9 }}},
     {   // Zone 0,0
       {{1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1},
         {6, 1}, {6, 2}, {-1, -1}, {-1, -1}},
    {{1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1},
        {6, 1}, {6, 2}, {-1, -1}, {-1, -1}},
       {{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5},
        {6, 1}, {1, 7}, {1, 8}, {1,9 }}},
  {   // Zone 0,0
       {{1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1},
         {6, 1}, {6, 2}, {-1, -1}, {-1, -1}},
    {{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5},
        {6, 1},{6, 2}, {-1, -1}, {-1, -1}},
       {{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5},
        {6, 1}, {1, 7}, {1, 8}, {1,9 }}}
};

// === Prototypes de fonctions ===
void initialiserZones();
void initialiserTFT();
void changerZone(int nouvelleZoneX, int nouvelleZoneY, const char* direction = "");
void afficherPersonnage();
void effacerCase(int colonne, int ligne);
void dessinerCase(int colonne, int ligne, uint16_t couleur);
void dessinerBitmap(int colonne, int ligne, const uint8_t* bitmap, uint16_t couleur);
void ramasserObjets();
void deplacementJoystick();
void gererCollisionBuissons();
void deplacerPerso(int dx, int dy);

// === Configuration initiale ===
void setup() {
    tft.begin();
    //tft.setRotation(1); // Orientation horizontale
    initialiserZones();
    initialiserTFT();
}

void loop() {
    if (millis() > perso.compteurVitesse + perso.vitesse) {
        deplacementJoystick();
        ramasserObjets();
        perso.compteurVitesse = millis();
    }
}

// === Initialisation des zones ===
void initialiserZones() {
    for (int i = 0; i < NB_ZONES; i++) {
        for (int j = 0; j < NB_ZONES; j++) {
            zones[i][j].nbBuissons = 0;
            zones[i][j].clefPresente = true;
            zones[i][j].positionClef = {8, 8};

            // Charger les buissons depuis mapBuissons
            int buissonIndex = 0;
            for (int k = 0; k < 9; k++) {
                if (mapBuissons[i][j][k][0] != -1 && mapBuissons[i][j][k][1] != -1) {
                    zones[i][j].positionBuissons[buissonIndex] = {mapBuissons[i][j][k][0], mapBuissons[i][j][k][1]};
                    buissonIndex++;
                }
            }
            zones[i][j].nbBuissons = buissonIndex;
        }
    }
}

// === Initialisation de l'écran TFT ===
void initialiserTFT() {
    tft.fillScreen(ILI9341_BLACK);
    changerZone(1, 1);
}

// === Dessins sur l'écran ===
void dessinerCase(int colonne, int ligne, uint16_t couleur) {
    int x = colonne * PIXELS_PAR_COLONNE;
    int y = ligne * PIXELS_PAR_LIGNE;
    tft.fillRect(x, y, PIXELS_PAR_COLONNE, PIXELS_PAR_LIGNE, couleur);
}

void effacerCase(int colonne, int ligne) {
    dessinerCase(colonne, ligne, ILI9341_BLACK);
}

void dessinerBitmap(int colonne, int ligne, const uint8_t* bitmap, uint16_t couleur) {
    int x = colonne * PIXELS_PAR_COLONNE;
    int y = ligne * PIXELS_PAR_LIGNE;
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            if (bitmap[i] & (1 << (7 - j))) {
tft.fillRect(x + j*3, y + i*3, 3, 3, couleur);            }
        }
    }
}

void afficherPersonnage() {
    dessinerBitmap(perso.position.colonne, perso.position.ligne, persoGraphique, ILI9341_YELLOW);
}

void ramasserObjets() {
    Zone &zone = zones[zoneActuelleX][zoneActuelleY];

    if (perso.position.colonne == zone.positionClef.colonne &&
        perso.position.ligne == zone.positionClef.ligne &&
        zone.clefPresente) {
        zone.clefPresente = false;
        effacerCase(zone.positionClef.colonne, zone.positionClef.ligne);
    }
}

void gererCollisionBuissons() {
    Zone &zone = zones[zoneActuelleX][zoneActuelleY];
    for (int i = 0; i < zone.nbBuissons; i++) {
        if (perso.position.colonne == zone.positionBuissons[i].colonne &&
            perso.position.ligne == zone.positionBuissons[i].ligne) {
            return; // Collision, ne pas bouger
        }
    }
}

void changerZone(int nouvelleZoneX, int nouvelleZoneY, const char* direction) {
    if (nouvelleZoneX < 0 || nouvelleZoneX >= NB_ZONES || nouvelleZoneY < 0 || nouvelleZoneY >= NB_ZONES) {
        return;
    }

    zones[zoneActuelleX][zoneActuelleY].positionPerso = perso.position;
    zoneActuelleX = nouvelleZoneX;
    zoneActuelleY = nouvelleZoneY;

    if (strcmp(direction, "droite") == 0) {
        perso.position = {0, perso.position.ligne};
    } else if (strcmp(direction, "gauche") == 0) {
        perso.position = {LCD_COLONNES - 1, perso.position.ligne};
    } else if (strcmp(direction, "haut") == 0) {
        perso.position = {perso.position.colonne, LCD_LIGNES - 1};
    } else if (strcmp(direction, "bas") == 0) {
        perso.position = {perso.position.colonne, 0};
    }

    tft.fillScreen(ILI9341_BLACK);
    Zone &zone = zones[zoneActuelleX][zoneActuelleY];

    if (zone.clefPresente) {
        dessinerBitmap(zone.positionClef.colonne, zone.positionClef.ligne, clefGraphique, ILI9341_BLUE);
    }

    for (int i = 0; i < zone.nbBuissons; i++) {
        dessinerBitmap(zone.positionBuissons[i].colonne, zone.positionBuissons[i].ligne, buissonGraphique, ILI9341_GREEN);
    }

    afficherPersonnage();
}

// === Gestion des déplacements ===
void deplacementJoystick() {
    J1 = analogRead(1);
    J2 = analogRead(0);

    if (J1 < SEUIL_ACTION_BAS) {
        if (perso.position.ligne < LCD_LIGNES - 1) {
            deplacerPerso(0, 1);
        } else if (zoneActuelleY < NB_ZONES - 1) {
            changerZone(zoneActuelleX, zoneActuelleY + 1, "bas");
        }
    }

    if (J1 > SEUIL_ACTION_HAUT) {
        if (perso.position.ligne > 0) {
            deplacerPerso(0, -1);
        } else if (zoneActuelleY > 0) {
            changerZone(zoneActuelleX, zoneActuelleY - 1, "haut");
        }
    }

    if (J2 < SEUIL_ACTION_BAS) {
        if (perso.position.colonne < LCD_COLONNES - 1) {
            deplacerPerso(1, 0);
        } else if (zoneActuelleX < NB_ZONES - 1) {
            changerZone(zoneActuelleX + 1, zoneActuelleY, "droite");
        }
    }

    if (J2 > SEUIL_ACTION_HAUT) {
        if (perso.position.colonne > 0) {
            deplacerPerso(-1, 0);
        } else if (zoneActuelleX > 0) {
            changerZone(zoneActuelleX - 1, zoneActuelleY, "gauche");
        }
    }
}

void deplacerPerso(int dx, int dy) {
    int nouvelleColonne = perso.position.colonne + dx;
    int nouvelleLigne = perso.position.ligne + dy;

    Zone &zone = zones[zoneActuelleX][zoneActuelleY];
    for (int i = 0; i < zone.nbBuissons; i++) {
        if (nouvelleColonne == zone.positionBuissons[i].colonne &&
            nouvelleLigne == zone.positionBuissons[i].ligne) {
            return;
        }
    }

    if (nouvelleColonne >= 0 && nouvelleColonne < LCD_COLONNES &&
        nouvelleLigne >= 0 && nouvelleLigne < LCD_LIGNES) {
        effacerCase(perso.position.colonne, perso.position.ligne);
        perso.position.colonne = nouvelleColonne;
        perso.position.ligne = nouvelleLigne;
        afficherPersonnage();
    }
}