String modeName(uint8_t mode) {
  if (language == 1) { // English
    switch (mode) {
      case 0:  return "Off";
      case 1:  return "Warm white";
      case 2:  return "Cool white";
      case 3:  return "Red";
      case 4:  return "Green";
      case 5:  return "Blue";
      case 6:  return "Yellow";
      case 7:  return "Orange";
      case 8:  return "Purple";
      case 9:  return "Cyan";
      case 10: return "Dim night light";
      case 11: return "TV flicker";
      case 12: return "Welding light";
      case 13: return "Fire flicker";
      case 14: return "Dim bedroom";
      case 15: return "Faulty neon tube";
      case 16: return "Street lamp / soft pulse";
      case 17: return "Random house light";
      case 18: return "Warning flash";
      case 19: return "Disco light";
      default: return "Unknown";
    }
  }
  if (language == 2) { // Deutsch
    switch (mode) {
      case 0:  return "Aus";
      case 1:  return "Warmweiß";
      case 2:  return "Kaltweiß";
      case 3:  return "Rot";
      case 4:  return "Grün";
      case 5:  return "Blau";
      case 6:  return "Gelb";
      case 7:  return "Orange";
      case 8:  return "Lila";
      case 9:  return "Cyan";
      case 10: return "Gedimmtes Nachtlicht";
      case 11: return "TV-Flimmern";
      case 12: return "Schweißlicht";
      case 13: return "Feuerflackern";
      case 14: return "Gedimmtes Schlafzimmer";
      case 15: return "Defekte Neonröhre";
      case 16: return "Straßenlampe / weicher Puls";
      case 17: return "Zufälliges Hauslicht";
      case 18: return "Warnblinken";
      case 19: return "Discolicht";
      default: return "Unbekannt";
    }
  }
  switch (mode) {
    case 0:  return "Slukket";
    case 1:  return "Varm hvid";
    case 2:  return "Kold hvid";
    case 3:  return "Rød";
    case 4:  return "Grøn";
    case 5:  return "Blå";
    case 6:  return "Gul";
    case 7:  return "Orange";
    case 8:  return "Lilla";
    case 9:  return "Cyan";
    case 10: return "Dæmpet natlys";
    case 11: return "TV-flimmer";
    case 12: return "Svejselys";
    case 13: return "Brand / ildflimmer";
    case 14: return "Dæmpet soveværelse";
    case 15: return "Defekt neonrør";
    case 16: return "Gadelampe / blød puls";
    case 17: return "Tilfældig beboelse / huslys";
    case 18: return "Advarselsblink";
    case 19: return "Diskolys";
    default: return "Ukendt";
  }
}
bool isEffectMode(uint8_t mode) {
  return mode >= 11 && mode <= 19;
}

CRGB getModeColor(uint8_t mode, uint8_t brightness) {
  CRGB c;

  switch (mode) {
    case 0:  c = CRGB::Black; break;
    case 1:  c = CRGB(255, 180, 80); break;       // varm hvid
    case 2:  c = CRGB(220, 240, 255); break;      // kold hvid
    case 3:  c = CRGB::Red; break;
    case 4:  c = CRGB::Green; break;
    case 5:  c = CRGB::Blue; break;
    case 6:  c = CRGB::Yellow; break;
    case 7:  c = CRGB::Orange; break;
    case 8:  c = CRGB::Purple; break;
    case 9:  c = CRGB::Cyan; break;
    case 10: c = CRGB(40, 22, 8); break;          // dæmpet natlys
    case 14: c = CRGB(80, 35, 12); break;         // dæmpet soveværelse
    default: c = CRGB(255, 180, 80); break;
  }

  c.nscale8_video(brightness);
  return c;
}

String modeHex(uint8_t mode) {
  switch (mode) {
    case 0:  return "#000000";
    case 1:  return "#ffb450";
    case 2:  return "#dcefff";
    case 3:  return "#ff0000";
    case 4:  return "#00cc00";
    case 5:  return "#004cff";
    case 6:  return "#ffff00";
    case 7:  return "#ff8c00";
    case 8:  return "#8000ff";
    case 9:  return "#00ffff";
    case 10: return "#281608";
    case 11: return "#88aaff";
    case 12: return "#bfe8ff";
    case 13: return "#ff5500";
    case 14: return "#50230c";
    case 15: return "#e8ffff";
    case 16: return "#ffb450";
    case 17: return "#ffc060";
    case 18: return "#ff0000";
    case 19: return "#ff00ff";
    default: return "#cccccc";
  }
}

void applyLedMode(int s, int i) {
  if (!isLedActive(s, i)) return;

  if (!ledState[s][i]) {
    leds[s][i] = CRGB::Black;
    return;
  }

  uint8_t mode = config[s][i].mode;
  uint8_t b = config[s][i].brightness;

  if (!isEffectMode(mode)) {
    leds[s][i] = getModeColor(mode, b);
  }
}

void previewLed(int globalIndex) {
  int s;
  int i;
  if (!globalToStripLed(globalIndex, s, i)) return;

  ledState[s][i] = true;
  applyLedMode(s, i);
  FastLED.show();
}

void clearInactiveLeds() {
  for (int s = 0; s < MAX_STRIPS; s++) {
    for (int i = ledCount[s]; i < MAX_LEDS_PER_STRIP; i++) {
      ledState[s][i] = false;
      leds[s][i] = CRGB::Black;
    }
  }
  FastLED.show();
}

void updateEffects() {
  static uint32_t lastShow = 0;
  bool changed = false;
  uint32_t now = millis();

  for (int s = 0; s < MAX_STRIPS; s++) {
    for (int i = 0; i < ledCount[s]; i++) {
      if (!ledState[s][i]) continue;

      uint8_t mode = config[s][i].mode;
      uint8_t b = config[s][i].brightness;

      if (!isEffectMode(mode)) continue;
      if (now < nextEffectUpdate[s][i]) continue;

      CRGB c = CRGB::Black;

      switch (mode) {
        case 11: { // TV-flimmer
          uint8_t r = random8(40, 180);
          uint8_t g = random8(60, 200);
          uint8_t bl = random8(120, 255);
          c = CRGB(r, g, bl);
          nextEffectUpdate[s][i] = now + random(40, 180);
          break;
        }

        case 12: { // Svejselys
          if (random8() < 45) {
            c = CRGB(random8(180, 255), random8(210, 255), 255);
            nextEffectUpdate[s][i] = now + random(20, 80);
          } else {
            c = CRGB::Black;
            nextEffectUpdate[s][i] = now + random(80, 700);
          }
          break;
        }

        case 13: { // Brand / ildflimmer
          c = CRGB(random8(160, 255), random8(20, 110), random8(0, 18));
          nextEffectUpdate[s][i] = now + random(35, 130);
          break;
        }

        case 14: { // Dæmpet soveværelse
          c = CRGB(80, 35, 12);
          nextEffectUpdate[s][i] = now + 500;
          break;
        }

        case 15: { // Defekt neonrør
          if (random8() < 70) c = CRGB(220, 255, 255);
          else c = CRGB::Black;
          nextEffectUpdate[s][i] = now + random(20, 450);
          break;
        }

        case 16: { // Gadelampe / blød puls
          uint8_t pulse = beatsin8(8, 150, 255, 0, globalLedIndex(s, i) * 17);
          c = CRGB(255, 180, 80);
          c.nscale8_video(pulse);
          nextEffectUpdate[s][i] = now + 40;
          break;
        }

        case 17: { // Tilfældig beboelse / huslys
          if (random8() < 120) c = CRGB(255, random8(130, 210), random8(50, 95));
          else c = CRGB::Black;
          nextEffectUpdate[s][i] = now + random(1500, 9000);
          break;
        }

        case 18: { // Advarselsblink
          effectPhase[s][i] = !effectPhase[s][i];
          c = effectPhase[s][i] ? CRGB::Red : CRGB::Black;
          nextEffectUpdate[s][i] = now + 450;
          break;
        }

        case 19: { // Diskolys
          c = CHSV(random8(), 255, 255);
          nextEffectUpdate[s][i] = now + random(80, 220);
          break;
        }
      }

      c.nscale8_video(b);
      leds[s][i] = c;
      changed = true;
    }
  }

  if (changed && now - lastShow > 20) {
    FastLED.show();
    lastShow = now;
  }
}
