#pragma once
#include <Adafruit_NeoPixel.h>

/*
 ===========================================================
    PhiMatrixEngine (RIGUEUR SCIENTIFIQUE)
    Architecture: Matrice 8×8 (évolutif 16×16)
    
    PRINCIPE: Brightness = Intensité réelle du phénomène
    Mapping linéaire: énergie (0.0-1.0) → brightness (30-255)
    
    Aucune interférence entre patterns
    Chaque pattern autonome avec son brightness scientifique
    
    8 INVISIBLES avec patterns personnalisés:
      1. IMU       → Spirale + remplissage (bright = vibration)
      2. Audio     → VU-mètre (bright = amplitude)
      3. EMI       → Neige (bright = intensité)
      4. Magnetic  → Symbole PHI (bright = delta magnétique)
      5. Proximity → Point IR autonome (bright = proximité)
      6. GPS       → 12 satellites (bright = qualité signal)
      7. BLE       → Signal (bright = RSSI)
      8. ENV       → Symbole PHI autonome (bright = deltas)
 ===========================================================
*/

// -------------------------------------------------------------------
// Configuration hardware (évolutif)
// -------------------------------------------------------------------
#define MATRIX_WIDTH  8
#define MATRIX_HEIGHT 8
#define NUM_LEDS_MATRIX (MATRIX_WIDTH * MATRIX_HEIGHT)

// -------------------------------------------------------------------
// Modes d'affichage
// -------------------------------------------------------------------
enum DisplayMode {
    DISPLAY_ALL = 0,      // 8 colonnes (vue d'ensemble)
    DISPLAY_IMU,          // Pattern ondes concentriques
    DISPLAY_AUDIO,        // Pattern VU-mètre
    DISPLAY_EMI,          // Pattern neige
    DISPLAY_MAG,          // Pattern champ magnétique
    DISPLAY_PROX,         // Pattern cercles proximité
    DISPLAY_GPS,          // Pattern satellites
    DISPLAY_BLE,          // Pattern signal radio
    DISPLAY_ENV,          // Pattern symbole PHI
    DISPLAY_MODE_COUNT
};

// -------------------------------------------------------------------
// Class
// -------------------------------------------------------------------
class PhiMatrixEngine {
public:
    PhiMatrixEngine();

    // Init
    bool begin(uint8_t pinMatrix, uint8_t brightness);

    // Mode management
    void setDisplayMode(DisplayMode mode) { _displayMode = mode; }
    DisplayMode getDisplayMode() const { return _displayMode; }
    const char* getDisplayModeName() const;

    // Render selon mode
    void renderAll(
        float imuE,
        float audE,
        float emiE,
        float magE,
        float proxE,
        float gpsE,
        float bleE,
        float envE,
        int gpsSats = 0,
        float deltaP = 0.0f,    // Delta pression (hPa)
        float deltaT = 0.0f,    // Delta température (°C)
        float deltaH = 0.0f,    // Delta humidité (%)
        const uint8_t* spectrum = nullptr  // Spectre 8 bandes (0-255)
    );

    // Brightness
    void setBrightness(uint8_t b);

private:
    Adafruit_NeoPixel* _matrix;
    DisplayMode _displayMode;
    uint8_t _spectrum[8];  // Spectre 8 bandes pour couleurs harmoniques

    // === PATTERNS PERSONNALISÉS ===
    void _renderIMU_wave(float energy);
    void _renderAudio_VUmeter(float energy);
    void _renderEMI_noise(float energy);
    void _renderMagnetic_field(float energy);
    void _renderProximity_circles(float proximity);
    void _renderGPS_satellites(int count, float quality);
    void _renderBLE_signal(float rssi);
    void _renderENV_PHI(float deltaP, float deltaT, float deltaH);

    // === VUE D'ENSEMBLE ===
    void _render8Columns(
        float imuE, float audE, float emiE, float magE,
        float proxE, float gpsE, float bleE, float envE
    );

    // === HELPERS ===
    void _fillZone(uint8_t x, uint8_t y, uint8_t w, uint8_t h, float energy, uint8_t r, uint8_t g, uint8_t b);
    void _setPixel(uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b);
    void _drawCircle(uint8_t cx, uint8_t cy, uint8_t radius, uint8_t r, uint8_t g, uint8_t b);
    void _drawCircleCentered(float radius, uint8_t r, uint8_t g, uint8_t b);
    float _normalizeEnergy(float e, float maxVal);
};