/*********************************************************************************************************************
 *
 *   ██████╗ ███╗   ███╗██████╗ ██╗     ██╗███╗   ██╗███████╗
 *  ██╔════╝ ████╗ ████║██╔══██╗██║     ██║████╗  ██║██╔════╝
 *  ██║      ██╔████╔██║██║  ██║██║     ██║██╔██╗ ██║█████╗
 *  ██║      ██║╚██╔╝██║██║  ██║██║     ██║██║╚██╗██║██╔══╝
 *  ╚██████╗ ██║ ╚═╝ ██║██████╔╝███████╗██║██║ ╚████║███████╗
 *   ╚═════╝ ╚═╝     ╚═╝╚═════╝ ╚══════╝╚═╝╚═╝  ╚═══╝╚══════╝
 *
 *  CmdLineKey.h — Sélection de plateforme, codes touches, machine d'état Telnet
 *  Version v24 — addCommands() : second tableau utilisateur optionnel
 *  Inclus AUTOMATIQUEMENT par CmdLine.h — ne pas inclure directement.
 *
 *********************************************************************************************************************
 *
 *  CONTENU DE CE FICHIER
 *  ─────────────────────
 *    1. Sélection de plateforme  → inclusion librairie réseau + typedef CmdLineClient
 *    2. Codes touches (KEY_xxx)  → retournés par readNetworkKey() et update()
 *    3. Machine d'état Telnet    → enum TelnetState (TS_INIT..TS_DONT)
 *    4. Constantes IAC Telnet    → CMDLINE_IAC, CMDLINE_WILL, CMDLINE_OPT_ECHO...
 *
 *********************************************************************************************************************
 *
 *  SÉLECTION DE PLATEFORME
 *  ────────────────────────
 *  Méthode 1 — Automatique (recommandée) :
 *    Rien à faire. Le compilateur détecte la cible et choisit la bonne
 *    librairie réseau. Les defines __AVR_..., ESP8266, ESP32 sont positionnés
 *    automatiquement par le toolchain Arduino.
 *
 *  Méthode 2 — Forcée dans le sketch .ino (override manuel) :
 *    Définir l'une de ces constantes AVANT #include <CmdLine.h> :
 *
 *    #define CMDLINE_PLATFORM_UNOR4        // Arduino UNO R4 + Shield Ethernet W5500
 *    #define CMDLINE_PLATFORM_ESP8266      // ESP8266 WiFi
 *    #define CMDLINE_PLATFORM_ESP32        // ESP32 WiFi
 *    #define CMDLINE_PLATFORM_ESP32_BT     // ESP32 Bluetooth Serial
 *
 *  Exemple dans le sketch .ino :
 *    #define CMDLINE_PLATFORM_ESP32
 *    #include <CmdLine.h>
 *
 *********************************************************************************************************************
 *
 *  PLATEFORMES SUPPORTÉES
 *  ──────────────────────
 *  ┌──────────────────────┬────────────────────────────┬──────────────────────┐
 *  │ Plateforme           │ Librairie réseau            │ Type client          │
 *  ├──────────────────────┼────────────────────────────┼──────────────────────┤
 *  │ UNO R4 + W5500       │ Ethernet.h                 │ EthernetClient       │
 *  │ ESP8266 WiFi         │ ESP8266WiFi.h              │ WiFiClient           │
 *  │ ESP32 WiFi           │ WiFi.h                     │ WiFiClient           │
 *  │ ESP32 Bluetooth      │ BluetoothSerial.h          │ BluetoothSerial      │
 *  └──────────────────────┴────────────────────────────┴──────────────────────┘
 *
 *  Note Bluetooth ESP32 :
 *    Le canal Telnet devient un canal Bluetooth Serial.
 *    L'API est similaire (available / read / write / print).
 *    La négociation IAC Telnet est désactivée automatiquement (CMDLINE_NO_IAC).
 *
 *********************************************************************************************************************
 *
 *  MACHINE D'ÉTAT TELNET — TelnetState
 *  ─────────────────────────────────────
 *  9 états persistants entre les appels de loop() :
 *
 *  TS_INIT ──0xFF──► TS_IAC ──WILL──► TS_WILL ──opt──► (répond WILL ECHO+SGA)
 *                           ──WONT──► TS_WONT ──opt──► (ignoré)
 *                           ──DO────► TS_DO   ──opt──► (répond WILL SGA / WONT)
 *                           ──DONT──► TS_DONT ──opt──► (ignoré)
 *  TS_INIT ──ESC───► TS_ESC ──'['──► TS_MATCH ──A/B/C/D──► KEY_UP/DOWN/RIGHT/LEFT
 *                           ──timeout 40ms──► TS_INIT
 *  TS_INIT ──CR────► TS_CR  ──LF ou NUL──► TS_INIT (absorbé, RFC 854)
 *
 *********************************************************************************************************************/

#ifndef __CMDLINE_KEY_H__
#define __CMDLINE_KEY_H__

#include <Arduino.h>


// ════════════════════════════════════════════════════════════════════════════
//  1. SÉLECTION DE PLATEFORME
//  ─────────────────────────────────────────────────────────────────────────
//  Priorité :
//    1. Override manuel dans le .ino (#define CMDLINE_PLATFORM_xxx)
//    2. Détection automatique par le compilateur (processeur cible)
// ════════════════════════════════════════════════════════════════════════════

#if defined(CMDLINE_PLATFORM_UNOR4)
// ── UNO R4 + Shield Ethernet W5500 ──────────────────────────────────────────
    #include <Ethernet.h>
    typedef EthernetClient  CmdLineClient;
    typedef EthernetServer  CmdLineServer;

#elif defined(CMDLINE_PLATFORM_ESP8266)
// ── ESP8266 WiFi ─────────────────────────────────────────────────────────────
    #include <ESP8266WiFi.h>
    typedef WiFiClient  CmdLineClient;
    typedef WiFiServer  CmdLineServer;

#elif defined(CMDLINE_PLATFORM_ESP32)
// ── ESP32 WiFi ───────────────────────────────────────────────────────────────
    #include <WiFi.h>
    typedef WiFiClient  CmdLineClient;
    typedef WiFiServer  CmdLineServer;

#elif defined(CMDLINE_PLATFORM_ESP32_BT)
// ── ESP32 Bluetooth Serial ───────────────────────────────────────────────────
// La négociation IAC Telnet est désactivée (Bluetooth n'est pas TCP).
    #include <BluetoothSerial.h>
    typedef BluetoothSerial  CmdLineClient;
    // Pas de CmdLineServer : le serveur BT est géré par BluetoothSerial directement
    #define CMDLINE_NETWORK_BLUETOOTH
    // Désactive la négociation IAC : inutile sur Bluetooth
    #ifndef CMDLINE_NO_IAC
        #define CMDLINE_NO_IAC
    #endif

// ── Détection automatique ────────────────────────────────────────────────────
#elif defined(ARDUINO_ARCH_RENESAS) || defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
    // UNO R4 (Renesas RA4M1)
    #include <Ethernet.h>
    typedef EthernetClient  CmdLineClient;
    typedef EthernetServer  CmdLineServer;

#elif defined(ESP8266)
    #include <ESP8266WiFi.h>
    typedef WiFiClient  CmdLineClient;
    typedef WiFiServer  CmdLineServer;

#elif defined(ESP32)
    #include <WiFi.h>
    typedef WiFiClient  CmdLineClient;
    typedef WiFiServer  CmdLineServer;

#else
    // Plateforme inconnue — essai avec WiFi générique
    #warning "CmdLineKey.h : plateforme non reconnue, WiFiClient utilisé par défaut."
    #include <WiFi.h>
    typedef WiFiClient  CmdLineClient;
    typedef WiFiServer  CmdLineServer;
#endif


// ════════════════════════════════════════════════════════════════════════════
//  2. CODES TOUCHES
//  Retournés par readNetworkKey() et update().
//  Valeurs > 0x7E pour ne pas entrer en conflit avec les ASCII imprimables.
// ════════════════════════════════════════════════════════════════════════════

#define KEY_NONE        -1      // Pas de touche disponible (attente)
#define KEY_RETURN      0x100   // ENTER  — CR (0x0D), LF (0x0A), CRLF, ou CR+NUL
#define KEY_BACKSPACE   0x101   // Backspace (0x08) ou DEL (0x7F)
#define KEY_TAB         0x102   // TAB (0x09) — déclenche la complétion
#define KEY_UP          0x103   // Flèche ↑  (ESC [ A) — historique précédent
#define KEY_DOWN        0x104   // Flèche ↓  (ESC [ B) — historique suivant
#define KEY_RIGHT       0x105   // Flèche →  (ESC [ C) — curseur droite
#define KEY_LEFT        0x106   // Flèche ←  (ESC [ D) — curseur gauche
// Codes 0x20..0x7E : caractère ASCII imprimable, retourné directement comme int


// ════════════════════════════════════════════════════════════════════════════
//  3. MACHINE D'ÉTAT TELNET — TelnetState
//
//  Stockée dans CanalState.tstate.
//  Persiste entre les appels de loop() car les séquences multi-octets
//  (ESC [ A, IAC WILL xx) peuvent arriver en plusieurs paquets TCP.
// ════════════════════════════════════════════════════════════════════════════

enum TelnetState {
    TS_INIT,    // Attente — état normal de repos
    TS_CR,      // CR (0x0D) reçu — absorbera le LF ou NUL suivant (RFC 854)
    TS_ESC,     // ESC (0x1B) reçu — attend '[' pour séquence ANSI flèche
    TS_MATCH,   // ESC[ reçu — attend la lettre finale A/B/C/D
    TS_IAC,     // IAC (0xFF) reçu — attend la commande Telnet
    TS_WILL,    // IAC WILL reçu — attend l'option
    TS_WONT,    // IAC WONT reçu — attend l'option (ignoré)
    TS_DO,      // IAC DO   reçu — attend l'option
    TS_DONT     // IAC DONT reçu — attend l'option (ignoré)
};


// ════════════════════════════════════════════════════════════════════════════
//  4. CONSTANTES IAC TELNET
//  RFC 854 — Telnet Protocol
//  RFC 857 — Telnet Echo Option
//  RFC 858 — Telnet Suppress Go Ahead
// ════════════════════════════════════════════════════════════════════════════

#define CMDLINE_IAC         0xFF    // Interpret As Command — marqueur de séquence Telnet
#define CMDLINE_WILL        0xFB    // Sender veut activer l'option
#define CMDLINE_WONT        0xFC    // Sender refuse / désactive l'option
#define CMDLINE_DO          0xFD    // Sender demande à l'autre d'activer l'option
#define CMDLINE_DONT        0xFE    // Sender demande à l'autre de désactiver l'option

#define CMDLINE_OPT_ECHO    0x01    // Option Echo (RFC 857)
#define CMDLINE_OPT_SGA     0x03    // Option Suppress Go Ahead (RFC 858)


#endif // __CMDLINE_KEY_H__
