#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

#define ENCODER_CLK 2
#define ENCODER_DT  3
#define ENCODER_SW  4

// LED pinleri
#define LED1_PIN 5
#define LED2_PIN 6
#define LED3_PIN 7
#define LED4_PIN 8
#define LED5_PIN 9

int selectedItem = 0; // Seçilen menü öğesinin indeksi
bool menuChanged = false; // Menü öğesi değiştiğinde true olur
bool okShown = false; // OK mesajı gösterildi mi?
unsigned long okStartTime = 0; // OK mesajının gösterilmeye başlandığı zaman
const unsigned long okDisplayDuration = 3000; // OK mesajının ekranda kalma süresi (milisaniye cinsinden)
const unsigned long LED5Duration = 100; // LED5'in yanma süresi (milisaniye cinsinden)

// Menü öğeleri
const char* menuItems[] = {
  "1. Reverb OFF",
  "2. Reverb ON",
  "3. Mix sat N",
  "4. Mix sat S",
  "5. Mix sat H",
  "6. Mix sat D",
  "7. Micro Tnltn 7edo",
  "8. Micro Tnl tn 9edo",
  "9. Micro Tnl tn 15edo",
  "10. Micro Tnl tn 17edo",
  "11. Micro Tnl tn 12edo",
  "12. Delay sync Unsycn",
  "13. Delay sync synced",
  "14. Signal routing Deafult",
  "15. Signal routing Reversed",
  "16. Filter Ladder LPF",
  "17. Filter SV LPF",
  "18. Filter SV BPF",
  "19. Filter SV HPF",
  "20. Filter HP-LF Series",
  "21. Filter HP-LF Paralel",
  "22. Filter Base Width",
  "23. Filter Base Width Notch",
  "24. Octave V1",
  "25. Octave V2",
  "26. Octave V3",
  "27. Octave V4",
  "28. LFO Adv func Rst lfo 1",
  "29. LFO Adv func Rst lfo 2",
  "30. LFO Adv func Copy",
  "31. LFO Adv func Cycle Lfo 2 WT",
  "32. LFO Adv func Lfo 1 SH",
  "33. LFO Adv func Lfo 1 SG",
  "34. LFO Adv func Lfo 2 SH",
  "35. LFO Adv func Lfo 2 SG",
  "36. LFO sync Lfo 1 Free",
  "37. LFO sync lfo 1 Sync",
  "38. LFO Sync lfo 2 free",
  "39. LFO sync Lfo 2 sync",
  "40. Portamento N",
  "41. Portamento F",
  "42. Portamento M",
  "43. Portamento S",
  "44. Calibrate 1v oct Calibrate",
  "45. Store",
  "46. 5v def",
  "47. 12v def"
};
const int menuSize = sizeof(menuItems) / sizeof(menuItems[0]);

void setup() {
  // Initialize LCD
  lcd.init();
  lcd.backlight();

  // Initialize encoder pins
  pinMode(ENCODER_CLK, INPUT);
  pinMode(ENCODER_DT, INPUT);
  pinMode(ENCODER_SW, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), readEncoder, FALLING);
  
  // LED pinlerini çıkış olarak ayarla
  pinMode(LED1_PIN, OUTPUT);
  pinMode(LED2_PIN, OUTPUT);
  pinMode(LED3_PIN, OUTPUT);
  pinMode(LED4_PIN, OUTPUT);
  pinMode(LED5_PIN, OUTPUT);
  
  updateMenu();
}

void readEncoder() {
  if (digitalRead(ENCODER_DT) == LOW) {
    selectedItem++;
    if (selectedItem >= menuSize) {
      selectedItem = 0;
    }
    menuChanged = true;
    okShown = false; // Her öğe değişiminde OK mesajını gizle
  } else {
    selectedItem--;
    if (selectedItem < 0) {
      selectedItem = menuSize - 1;
    }
    menuChanged = true;
    okShown = false; // Her öğe değişiminde OK mesajını gizle
  }
}

void updateMenu() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(menuItems[selectedItem]);
}

void loop() {
  if (menuChanged) {
    updateMenu();
    menuChanged = false;
    okShown = false; // Her menü değişiminde OK mesajını gizle
  }

  // Encoder düğmesi basıldığında OK mesajını göster
  if (digitalRead(ENCODER_SW) == LOW) {
    okStartTime = millis(); // SW düğmesine basıldığında OK mesajının gösterilmeye başlandığı zamanı sıfırla
    okShown = true;
    // LED sekansları
    if (selectedItem == 0) { // 1. menü öğesi için LED sekansı
      LEDSequence1();
    } else if (selectedItem == 1) { // 2. menü öğesi için LED sekansı
      LEDSequence2();
    } // Diğer menü öğeleri için gerekirse buraya eklenebilir
    
    // OK mesajını göster
    lcd.setCursor(15, 1);
    lcd.print("OK");
    delay(okDisplayDuration); // OK mesajını belirli bir süre göster
    lcd.setCursor(15, 1);
    lcd.print("  "); // OK mesajını temizle
    okShown = false; // OK mesajı gizlendi
  }

  delay(50); // Bir süre bekleyerek encoder okumalarını rahatlatırız
}

// 1. menü öğesi için LED sekansı
void LEDSequence1() {
  // LED5_PIN yansın
  digitalWrite(LED5_PIN, HIGH);
  delay(LED5Duration); // LED5_PIN'in belirli bir süre yanmasını sağlar
  
  // LED4_PIN arka arkaya 2 defa yanıp sönsün
  for (int i = 0; i < 2; i++) {
    digitalWrite(LED4_PIN, HIGH);
    delay(300);
    digitalWrite(LED4_PIN, LOW);
    delay(300);
  }
  
  // LED1_PIN yanıp sönsün
  digitalWrite(LED1_PIN, HIGH);
  delay(300);
  digitalWrite(LED1_PIN, LOW);
  
  // Tüm LED'leri söndür
  digitalWrite(LED2_PIN, LOW);
  digitalWrite(LED3_PIN, LOW);
  digitalWrite(LED4_PIN, LOW);
  
  // LED5_PIN'i kapat, en son sönen LED olsun
  digitalWrite(LED5_PIN, LOW);
}

// 2. menü öğesi için LED sekansı
void LEDSequence2() {
  // LED5_PIN yansın
  digitalWrite(LED5_PIN, HIGH);
  delay(LED5Duration); // LED5_PIN'in belirli bir süre yanmasını sağlar
  
  // LED4_PIN arka arkaya 2 defa yanıp sönsün
  for (int i = 0; i < 2; i++) {
    digitalWrite(LED4_PIN, HIGH);
    delay(300);
    digitalWrite(LED4_PIN, LOW);
    delay(300);
  }
  
  // LED2_PIN yanıp sönsün
  digitalWrite(LED2_PIN, HIGH);
  delay(300);
  digitalWrite(LED2_PIN, LOW);
  
  // Tüm LED'leri söndür
  digitalWrite(LED1_PIN, LOW);
  digitalWrite(LED3_PIN, LOW);
  digitalWrite(LED4_PIN, LOW);
  
  // LED5_PIN'i kapat, en son sönen LED olsun
  digitalWrite(LED5_PIN, LOW);
}