#include Wire.h
#include LiquidCrystal_I2C.h
#include DHT.h

#define DHTPIN 7
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 20, 4);

const unsigned long intervalZakladni = 14400000UL;  4 hodiny v ms
unsigned long casPoslednihoMereni[2] = {0, 0};
unsigned long casZaliti[2] = {0, 0};
int davka[2] = {60000, 60000};  počáteční doba zalévání v ms
int vlhkostPred[2] = {0, 0};
int vlhkostMin[6] = {0, 800, 700, 600, 500, 400};  index 0 = nevybráno
int vlhkostMax[6] = {0, 950, 850, 750, 650, 550};  horní hranice podle typu

const long k = 200000;


const int btnUp = 2;
const int btnDown = 3;
const int btnSelect = 4;
const int btnBack = 5;

int menuIndex = 0;
const int maxMenuItems = 2;  Květináč 1, Květináč 2

int typRostliny[2] = {0, 0};  typy 1–5, 0 = nevybráno
String typyRostlin[] = {---, Typ 1, Typ 2, Typ 3, Typ 4, Typ 5};

float t = 0.0;
float h = 0.0;

unsigned long posledniInterakce = 0;
bool lcdZapnuto = true;
const unsigned long timeoutLCD = 10000;  10 sekund

const int HISTORIE_POCET = 6;

int historieTeplota[HISTORIE_POCET] = {0};
int historieVlhkostVzduchu[HISTORIE_POCET] = {0};
int historiePuda1[HISTORIE_POCET] = {0};
int historiePuda2[HISTORIE_POCET] = {0};

int poziceHistorie = 0;
unsigned long casPoslednihoUlozeni = 0;
const unsigned long intervalUlozeni = 5000;  1 minuta (pro testování; reálně třeba 4 h)




void setup() {
  lcd.init();
  lcd.backlight();
  dht.begin();

  pinMode(btnUp, INPUT_PULLUP);
  pinMode(btnDown, INPUT_PULLUP);
  pinMode(btnSelect, INPUT_PULLUP);
  pinMode(btnBack, INPUT_PULLUP);

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(Zavlazovaci system);
  delay(2000);
  lcd.clear();
}

void loop() {
  if (millis() - posledniInterakce  timeoutLCD && lcdZapnuto) {
    lcd.noBacklight();
    lcdZapnuto = false;
  }

  t = dht.readTemperature();
  h = dht.readHumidity();

Serial.println(t);
Serial.println(h);


  lcd.setCursor(0, 0);
  lcd.print((menuIndex == 0)  (char)126  ' ');
  lcd.print( Kvetinac 1     );

  lcd.setCursor(0, 1);
  lcd.print((menuIndex == 1)  (char)126  ' ');
  lcd.print( Kvetinac 2     );

  lcd.setCursor(12, 3);
  lcd.print((int)t);
  lcd.print(C );
  lcd.setCursor(16, 3);
  lcd.print((int)h);
  lcd.print(% );

  if (digitalRead(btnUp) == LOW) {
    if (!lcdZapnuto) {
      lcd.backlight();
      lcdZapnuto = true;
    }
    posledniInterakce = millis();
    menuIndex = (menuIndex - 1 + maxMenuItems) % maxMenuItems;
    delay(200);
  }

  if (digitalRead(btnDown) == LOW) {
    if (!lcdZapnuto) {
      lcd.backlight();
      lcdZapnuto = true;
    }
    posledniInterakce = millis();
    menuIndex = (menuIndex + 1) % maxMenuItems;
    delay(200);
  }

  if (digitalRead(btnSelect) == LOW) {
    if (!lcdZapnuto) {
      lcd.backlight();
      lcdZapnuto = true;
    }
    posledniInterakce = millis();
    showPodmenu(menuIndex);
    delay(300);
  }

  if (millis() - casPoslednihoUlozeni  intervalUlozeni) {
  historieTeplota[poziceHistorie] = (int)t;
  historieVlhkostVzduchu[poziceHistorie] = (int)h;

  historiePuda1[poziceHistorie] = analogRead(A0);
  historiePuda2[poziceHistorie] = analogRead(A1);

  poziceHistorie = (poziceHistorie + 1) % HISTORIE_POCET;
  casPoslednihoUlozeni = millis();

  
}
kontrolaZalivaniPokrocile(0);  květináč 1
kontrolaZalivaniPokrocile(1);  květináč 2


}

void showPodmenu(int kvetinac) {
  while (digitalRead(btnSelect) == LOW  digitalRead(btnBack) == LOW) {
    delay(10);  počkej na uvolnění tlačítek
  }

  int submenuIndex = 0;
  const int maxSubmenuItems = 2;
  bool needsUpdate = true;

  while (true) {
    if (needsUpdate) {
      lcd.clear();

      lcd.setCursor(0, 0);
      lcd.print(Typ );
      lcd.print(typyRostlin[typRostliny[kvetinac]]);

      lcd.setCursor(0, 1);
      lcd.print((submenuIndex == 0)  (char)126  ' ');
      lcd.print( Vybrat typ rostlin);

      lcd.setCursor(0, 2);
      lcd.print((submenuIndex == 1)  (char)126  ' ');
      lcd.print( Historie mer.);

      needsUpdate = false;
    }

    if (digitalRead(btnUp) == LOW) {
      if (!lcdZapnuto) {
        lcd.backlight();
        lcdZapnuto = true;
      }
      posledniInterakce = millis();
      submenuIndex = (submenuIndex - 1 + maxSubmenuItems) % maxSubmenuItems;
      needsUpdate = true;
      delay(200);
    }

    if (digitalRead(btnDown) == LOW) {
      if (!lcdZapnuto) {
        lcd.backlight();
        lcdZapnuto = true;
      }
      posledniInterakce = millis();
      submenuIndex = (submenuIndex + 1) % maxSubmenuItems;
      needsUpdate = true;
      delay(200);
    }

    if (digitalRead(btnSelect) == LOW) {
  if (!lcdZapnuto) {
    lcd.backlight();
    lcdZapnuto = true;
  }
  posledniInterakce = millis();

  if (submenuIndex == 0) {
  vyberTypRostliny(kvetinac);
} else if (submenuIndex == 1) {
  zobrazMenuHistorie(kvetinac);
}


  delay(300);
  needsUpdate = true;  znovu překreslí podmenu
}


    if (digitalRead(btnBack) == LOW) {
      if (!lcdZapnuto) {
        lcd.backlight();
        lcdZapnuto = true;
      }
      posledniInterakce = millis();
      delay(200);
      break;
    }

    


  }

  lcd.clear();
}
void vyberTypRostliny(int kvetinac) {
while (digitalRead(btnSelect) == LOW  digitalRead(btnBack) == LOW) {
  delay(10);  počkej, než uživatel pustí tlačítko
}


  int vybranyTyp = typRostliny[kvetinac];
  bool needsUpdate = true;

  while (true) {
    if (needsUpdate) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(Zvol typ (1-5));

      lcd.setCursor(0, 1);
      lcd.print((char)126);  šipka
      lcd.print( Typ );
      lcd.print(vybranyTyp);

      needsUpdate = false;
    }

    if (digitalRead(btnUp) == LOW) {
      vybranyTyp = (vybranyTyp  5)  vybranyTyp + 1  1;
      needsUpdate = true;
      delay(200);
    }

    if (digitalRead(btnDown) == LOW) {
      vybranyTyp = (vybranyTyp  1)  vybranyTyp - 1  5;
      needsUpdate = true;
      delay(200);
    }

    if (digitalRead(btnSelect) == LOW) {
      typRostliny[kvetinac] = vybranyTyp;
      casPoslednihoMereni[kvetinac] = millis();
      vlhkostPred[kvetinac] = analogRead((kvetinac == 0)  A0  A1);

      delay(300);
      break;
    }

    if (digitalRead(btnBack) == LOW) {
      delay(300);
      break;
    }
  }

  

  lcd.clear();
}
void zobrazHistorii(int pole, String popisek, String jednotka) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(popisek + );

  for (int i = 0; i  3; i++) {
    lcd.setCursor(i  6, 1);
    lcd.print(pole[(poziceHistorie + i) % HISTORIE_POCET]);
    lcd.print(jednotka);
  }

  for (int i = 3; i  6; i++) {
    lcd.setCursor((i - 3)  6, 2);
    lcd.print(pole[(poziceHistorie + i) % HISTORIE_POCET]);
    lcd.print(jednotka);
  }

  

  while (digitalRead(btnBack) == HIGH) {
    delay(10);
  }
  delay(200);
  lcd.clear();
}

void zobrazMenuHistorie(int kvetinac) {
  int index = 0;
  const int maxIndex = 3;
  bool needsUpdate = true;

  while (digitalRead(btnSelect) == LOW  digitalRead(btnBack) == LOW) {
    delay(10);
  }

  while (true) {
    if (needsUpdate) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(Vyber historii);

      lcd.setCursor(0, 1);
      lcd.print((index == 0)  (char)126  ' ');
      lcd.print( Teplota vzduchu);

      lcd.setCursor(0, 2);
      lcd.print((index == 1)  (char)126  ' ');
      lcd.print( Vlhkost vzduchu);

      lcd.setCursor(0, 3);
      lcd.print((index == 2)  (char)126  ' ');
      lcd.print( Vlhkost pudy);

      needsUpdate = false;
    }

    if (digitalRead(btnUp) == LOW) {
      index = (index - 1 + maxIndex) % maxIndex;
      needsUpdate = true;
      delay(200);
    }

    if (digitalRead(btnDown) == LOW) {
      index = (index + 1) % maxIndex;
      needsUpdate = true;
      delay(200);
    }

    if (digitalRead(btnSelect) == LOW) {
      delay(200);
      if (index == 0) zobrazHistorii(historieTeplota, Teplota, C);
      else if (index == 1) zobrazHistorii(historieVlhkostVzduchu, Vzduch, %);
      else if (index == 2) zobrazHistorii(kvetinac == 0  historiePuda1  historiePuda2, Puda, );
      needsUpdate = true;
    }

    if (digitalRead(btnBack) == LOW) {
      delay(200);
      break;
    }
  }

  lcd.clear();
}

void kontrolaZalivaniPokrocile(int kvetinac) {
  int pinRele = (kvetinac == 0)  8  9;
  int pinVlhkost = (kvetinac == 0)  A0  A1;
  int typ = typRostliny[kvetinac];

  if (typ  1  typ  5) return;

  unsigned long aktualniCas = millis();
  if (aktualniCas - casPoslednihoMereni[kvetinac]  intervalZakladni  2) return;

  float f_prostredi = (1 + (t - 25)  0.03)  (1 + (50 - h)  0.02);
  f_prostredi = constrain(f_prostredi, 0.5, 1.5);
  unsigned long interval = intervalZakladni  f_prostredi;

  if (aktualniCas - casPoslednihoMereni[kvetinac] = interval) {
    int vlhkost = analogRead(pinVlhkost);

    if (vlhkost  vlhkostMin[typ] && vlhkost  vlhkostMax[typ]) {
      vlhkostPred[kvetinac] = vlhkost;
      digitalWrite(pinRele, LOW);
      delay(davka[kvetinac]);
      digitalWrite(pinRele, HIGH);

      delay(1000);

      int vlhkostPo = analogRead(pinVlhkost);
      float delta = vlhkostPo - vlhkostPred[kvetinac];
      float cas = davka[kvetinac]  1000.0;
      float ucinnost = delta  cas;
      float rozsah = vlhkostMax[typ] - vlhkostMin[typ];
      float cilova = rozsah  0.6  cas;
      long deltaD = (cilova - ucinnost)  k;
      deltaD = constrain(deltaD, -250000, 250000);
      float limit = vlhkostMin[typ] + rozsah  0.6;

      if (vlhkostPo = limit) {
        if (deltaD  0) {
          davka[kvetinac] += deltaD;
        }
      } else {
        davka[kvetinac] += deltaD;
      }

      davka[kvetinac] = constrain(davka[kvetinac], 500, 600000);
    }

    casPoslednihoMereni[kvetinac] = aktualniCas;
  }
}

