#include <BleKeyboard.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

BleKeyboard bleKeyboard("ESP32 Keyboard", "ESP32", 100);

#define LED_BUILTIN 2
#define BUTTON_1 12  // Ctrl+C
#define BUTTON_2 13  // Ctrl+V
#define BUTTON_3 32  // Ctrl+Z
#define BUTTON_4 33  // Alt+Space
#define BUTTON_5 4   // Windows+Shift+T
#define BUTTON_6 0   // Windows+Ctrl+Alt+R
#define BUTTON_7 14  // Alt+Tab
#define BUTTON_8 27  // Windows+V

String receivedText = "STREAMDESK DU FUTUR";
int scrollOffset;
bool usbConnected = false;

void setup() {
    Serial.begin(115200);
    pinMode(LED_BUILTIN, OUTPUT);
    pinMode(BUTTON_1, INPUT_PULLUP);
    pinMode(BUTTON_2, INPUT_PULLUP);
    pinMode(BUTTON_3, INPUT_PULLUP);
    pinMode(BUTTON_4, INPUT_PULLUP);
    pinMode(BUTTON_5, INPUT_PULLUP);
    pinMode(BUTTON_6, INPUT_PULLUP);
    pinMode(BUTTON_7, INPUT_PULLUP);
    pinMode(BUTTON_8, INPUT_PULLUP);

    bleKeyboard.begin();

    if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
        Serial.println(F("Échec de l'initialisation de l'écran OLED"));
        for (;;);
    }
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);
    display.display();

    scrollOffset = SCREEN_WIDTH;
}

void loop() {
    if (Serial.available()) {
        char buffer[21];
        int len = Serial.readBytesUntil('\n', buffer, 20);
        buffer[len] = '\0';
        receivedText = String(buffer);
        digitalWrite(LED_BUILTIN, HIGH);
        delay(100);
        digitalWrite(LED_BUILTIN, LOW);
        scrollOffset = SCREEN_WIDTH;
    }

    display.clearDisplay();
    display.setCursor(scrollOffset, 0);
    display.print(receivedText);
    display.display();
    delay(500);

    scrollOffset++;
    int textWidth = receivedText.length() * 6;
    if (scrollOffset > SCREEN_WIDTH) {
        scrollOffset = -textWidth;
    }

    if (bleKeyboard.isConnected()) {
        checkButton(BUTTON_1, KEY_LEFT_CTRL, 'c', "Ctrl+C");
        checkButton(BUTTON_2, KEY_LEFT_CTRL, 'v', "Ctrl+V");
        checkButton(BUTTON_3, KEY_LEFT_CTRL, 'z', "Ctrl+Z");
        checkButton(BUTTON_4, KEY_LEFT_ALT, 32, "Alt+Space");
        checkButton(BUTTON_5, KEY_LEFT_GUI, KEY_LEFT_SHIFT, 't', "Windows+Shift+T");
        checkButton(BUTTON_6, KEY_LEFT_GUI, KEY_LEFT_CTRL, KEY_LEFT_ALT, 'r', "Windows+Ctrl+Alt+R");
        checkButton(BUTTON_7, KEY_LEFT_ALT, KEY_TAB, "Alt+Tab");
        checkButton(BUTTON_8, KEY_LEFT_GUI, 'v', "Windows+V");
    }
}

void checkButton(int button, uint8_t mod1, uint8_t key, String action) {
    if (digitalRead(button) == LOW) {
        sendShortcut(mod1, key);
        displayAction(action);
    }
}

void checkButton(int button, uint8_t mod1, uint8_t mod2, uint8_t key, String action) {
    if (digitalRead(button) == LOW) {
        sendShortcut(mod1, mod2, key);
        displayAction(action);
    }
}

void checkButton(int button, uint8_t mod1, uint8_t mod2, uint8_t mod3, uint8_t key, String action) {
    if (digitalRead(button) == LOW) {
        sendShortcut(mod1, mod2, mod3, key);
        displayAction(action);
    }
}

void sendShortcut(uint8_t mod1, uint8_t key) {
    bleKeyboard.press(mod1);
    bleKeyboard.press(key);
    delay(100);
    bleKeyboard.releaseAll();
    delay(200);
}

void sendShortcut(uint8_t mod1, uint8_t mod2, uint8_t key) {
    bleKeyboard.press(mod1);
    bleKeyboard.press(mod2);
    bleKeyboard.press(key);
    delay(100);
    bleKeyboard.releaseAll();
    delay(200);
}

void sendShortcut(uint8_t mod1, uint8_t mod2, uint8_t mod3, uint8_t key) {
    bleKeyboard.press(mod1);
    bleKeyboard.press(mod2);
    bleKeyboard.press(mod3);
    bleKeyboard.press(key);
    delay(100);
    bleKeyboard.releaseAll();
    delay(200);
}

void displayAction(String action) {
    display.clearDisplay();
    display.setCursor(0, 0);
    display.print("Commande: ");
    display.print(action);
    display.display();
}
