#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_NeoPixel.h>
// Adresse des I2C-Displays (kann je nach Display variieren)
#define I2C_ADDR 0x27
// Pin, an dem die WS2812 LEDs angeschlossen sind
#define LED_PIN 6

// Anzahl der LEDs
#define NUM_LEDS 8
// Erstelle ein NeoPixel-Objekt
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

// Initialisiere das Display mit der Adresse, 16 Spalten und 2 Zeilen
LiquidCrystal_I2C lcd(I2C_ADDR, 16, 2);

// Variablen für die Scrollpositionen und Zeitstempel
//int pos1 = 0;
//int pos2 = 0;
//unsigned long prevMillis1 = 0;
//unsigned long prevMillis2 = 0;

void setup() {
  // Initialisierung des LCD
  lcd.init();
  lcd.backlight();
  // Initialisiere das LED-Strip-Objekt
  strip.begin();
  strip.show(); // Alle LEDs aus

}
//int myPins[] = {2, 4, 8, 3, 6, 4};
  uint32_t colors1[] = {
    0b000000000000000000000000,  // LED 1: Rot
    0b010000000000000000000000,  // LED 2: Rot
    0b010010000000000000000000,  // LED 3: Rot
    0b010010010000000000000000,  // LED 4: Rot
    0b010010010010000000000000,  // LED 5: Rot
    0b010010010010010000000000,  // LED 6: Rot
    0b010010010010010010000000,  // LED 7: Rot
    0b010010010010010010010000,   // LED 8: Rot
    0b010010010010010010010000,   // LED 8: Rot
    0b010010010010010010010110,   // LED 8: Rot
    0b001001001001010010010100,   // LED 8: Rot
    0b010010010010010010010100,   // LED 8: Rot
    0b010010010010010010010100,   // LED 8: Rot
    0b010010010010010010010100,   // LED 8: Rot
    0b010010010010010010010100   // LED 8: Rot
};
#define AUS   0
#define ROT   1
#define GRUEN 2
#define GELB  3
#define BLAU  4
#define Violet 5
#define Pink 6
#define Weiss 7 

// uint8_t colors[NUM_LEDS] = {ROT, Violet, Pink, GELB, Weiss, GRUEN, BLAU, BLAU};
uint8_t colors[] = {
    (GRUEN, AUS, AUS, AUS, AUS, AUS, AUS, AUS),  // LED 1: Rot
    (GRUEN, GRUEN, Pink, AUS, AUS, AUS, AUS, AUS),  // LED 1: Rot
    (GRUEN, Violet, Pink, AUS, AUS, AUS, AUS, AUS),  // LED 1: Rot
    (GRUEN, GRUEN, Pink, GELB, Violet, GRUEN, Weiss, BLAU),  // LED 1: Rot
    (GRUEN, GRUEN, Pink, GELB, Weiss, GRUEN, BLAU, Weiss),  // LED 1: Rot
    (GRUEN, GRUEN, Pink, GELB, Violet, GELB, BLAU, BLAU),  // LED 1: Rot
    (Pink, GRUEN, Pink, GELB, Weiss, Weiss, BLAU, BLAU),  // LED 1: Rot
    (GELB, GRUEN, Pink, GELB, Violet, GELB, BLAU, BLAU)  // LED 1: Rot
};
  unsigned long prevMillis = 0;

 void loop() {
  // Beispielaufruf der Funktion
//  displayScroll("Hallo Welt! Dies ist eine lange Zeile.", "Arduino I2C Display Scroll Beispiel", 500, 500);
  displayScroll("  Hallo Welt!   ", "0123456789ABCDEF0", 500, 500);
/*
  uint32_t colors[NUM_LEDS] = {
    strip.Color(0, 0xFF, 0),  // LED 1: Rot
    strip.Color(0, 0xFF, 0),  // LED 2: Rot
    strip.Color(0, 0xFF, 0),  // LED 3: Rot
    strip.Color(0, 0xFF, 0),  // LED 4: Rot
    strip.Color(255, 0xFF, 0),  // LED 5: Rot
    strip.Color(255, 0xFF, 0),  // LED 6: Rot
    strip.Color(55, 0, 0),  // LED 7: Rot
    strip.Color(55, 0, 0)   // LED 8: Rot
  };
  // Beispielaufruf der Funktion
  setLedColors(colors);
  delay(1000); // Warte 1 Sekunde
*/
//    uint32_t randNumber = random(0, 0xFFFFF);
//  uint32_t ledColors = 0b101010101010101010101010; // Jede LED abwechselnd Rot und Grün
  //unsigned long currentMillis = millis();

  //  if (currentMillis > (prevMillis + 300)) {
  //    prevMillis = currentMillis;
  //    uint32_t randNumber = random(0, 8);
  //    setLedColors(colors[randNumber]);
  //  }//  delay(1000); // Warte 1 Sekunde
  uint8_t colors[NUM_LEDS] = {ROT, Violet, Pink, GELB, Weiss, GRUEN, BLAU, BLAU};
  
  // Beispielaufruf der Funktion
  setLedColors(colors);


}

/**
 * Funktion zum Anzeigen von Text auf einem 2x16 I2C Display
 * @param line1 Text für die erste Zeile
 * @param line2 Text für die zweite Zeile
 * @param speed1 Scrollgeschwindigkeit für die erste Zeile (in Millisekunden)
 * @param speed2 Scrollgeschwindigkeit für die zweite Zeile (in Millisekunden)
 */
void displayScroll(String line1, String line2, int speed1, int speed2) {
  unsigned long currentMillis = millis();
  int len1 = line1.length();
  int len2 = line2.length();
  static int pos1 = 0;
  static int pos2 = 0;
  static unsigned long prevMillis1 = 0;
  static unsigned long prevMillis2 = 0;

  // Wenn die Länge der Zeichenkette <= 16 ist, muss nicht gescrollt werden
  if (len1 <= 16) {
    lcd.setCursor(0, 0);
    lcd.print(line1);
  } else {
    if (currentMillis - prevMillis1 >= speed1) {
      prevMillis1 = currentMillis;
      lcd.setCursor(0, 0);
      lcd.print(line1.substring(pos1, pos1 + 16));
      pos1++;
      if (pos1 > len1 - 16) pos1 = 0; // Zurück zum Anfang scrollen
    }
  }

  if (len2 <= 16) {
    lcd.setCursor(0, 1);
    lcd.print(line2);
  } else {
    if (currentMillis - prevMillis2 >= speed2) {
      prevMillis2 = currentMillis;
      lcd.setCursor(0, 1);
      lcd.print(line2.substring(pos2, pos2 + 16));
      pos2++;
      if (pos2 > len2 - 16) pos2 = 0; // Zurück zum Anfang scrollen
    }
  }
}
/**
 * Setzt die Farben von 8 WS2812 RGB-LEDs basierend auf einem long int
 * @param colors Ein long int, der die Farben der 8 LEDs bestimmt
 *
void setLedColors(unsigned long long colors) {
  // Jede LED erhält 3 Bytes (24 Bit insgesamt)
  for (int i = 0; i < NUM_LEDS; i++) {
    // Extrahiere die Farbe für die LED
    uint8_t red = (colors >> (24 * (NUM_LEDS - 1 - i) + 16)) & 0xFF;
    uint8_t green = (colors >> (24 * (NUM_LEDS - 1 - i) + 8)) & 0xFF;
    uint8_t blue = (colors >> (24 * (NUM_LEDS - 1 - i))) & 0xFF;

    // Setze die Farbe der LED
    strip.setPixelColor(i, strip.Color(red, green, blue));
  }

  // Aktualisiere die LEDs
  strip.show();
}
*/
/**
 * Setzt die Farben von 8 WS2812 RGB-LEDs basierend auf einem Array
 * @param colors Ein Array von uint32_t, das die Farben der 8 LEDs bestimmt

void setLedColors(uint32_t colors[NUM_LEDS]) {
  for (int i = 0; i < NUM_LEDS; i++) {
    // Setze die Farbe der LED
    strip.setPixelColor(i, colors[i]);
  }
  
  // Aktualisiere die LEDs
  strip.show();
}
 */
/**
 * Setzt die Farben von 8 WS2812 RGB-LEDs basierend auf einem 24-Bit-Wert
 * @param colors Ein 24-Bit-Wert, der die Farben der 8 LEDs bestimmt
 
void setLedColors(uint32_t colors, int speed ) {
  static unsigned long prevMillis = 0;
  unsigned long currentMillis = millis();

    if (currentMillis - prevMillis >= speed) {
      prevMillis = currentMillis;

       for (int i = 0; i < NUM_LEDS; i++) {
       // Extrahiere die 3 Bits für die LED
        uint8_t colorBits = (colors >> (3 * (NUM_LEDS - 1 - i))) & 0b111;
    // Initialisiere Farben
        uint8_t red = (colorBits & 0b100) ? 255 : 0;
        uint8_t green = (colorBits & 0b010) ? 255 : 0;
        uint8_t blue = (colorBits & 0b001) ? 255 : 0;
    // Setze die Farbe der LED
        strip.setPixelColor(i, strip.Color(red, green, blue));
       }
  
  // Aktualisiere die LEDs
    strip.show();
    }
}
*/
/**
 * Setzt die Farben von 8 WS2812 RGB-LEDs basierend auf einem Array
 * @param colors Ein Array von uint8_t, das die Farben der 8 LEDs bestimmt
 */
void setLedColors(uint8_t colors[NUM_LEDS]) {
  for (int i = 0; i < NUM_LEDS; i++) {
    uint32_t color;
    switch (colors[i]) {
      case ROT:
        color = strip.Color(255, 0, 0);
        break;
      case GRUEN:
        color = strip.Color(0, 255, 0);
        break;
      case GELB:
        color = strip.Color(255, 255, 0);
        break;
      case BLAU:
        color = strip.Color(0, 0, 255);
        break;
      case Violet:
        color = strip.Color(255, 0, 255);
        break;
      case Pink:
        color = strip.Color(0, 255, 255);
        break;
      case Weiss:
        color = strip.Color(255, 255, 255);
        break;
      default:
        color = strip.Color(0, 0, 0); // Standard: aus
        break;
    }
    strip.setPixelColor(i, color);
  }
  
  // Aktualisiere die LEDs
  strip.show();
}