#include <U8g2lib.h>

U8X8_SSD1306_128X64_NONAME_HW_I2C display(U8X8_PIN_NONE);

#include <Adafruit_BMP280.h> // Библиотека для работы с датчиком BMP280

// Для подключения по шине I2C
Adafruit_BMP280 bmp;

unsigned long vivod = 0;
unsigned long vivodM = 0;
unsigned long obndat = 0;

// uint32_t vivod1 = 0;
// int r = 0;

int vivodvalue = 200;
int vivodmenu = 500;
int obnvalue = 100;

#define M1 5
#define M2 6

#define D1 A0

#define PWR_PIN 7
bool Triger = 0;

#define CLK 2
#define DT 3
#define SW 4
#include "GyverEncoder.h"
Encoder enc1(CLK, DT, SW, TYPE2);  // для работы c кнопкой

int c = 0, a = 0;

uint8_t disp = 0;

// int KV[9] = {0, 500, 1000, 500, 1000};
int skvaj = 0, skvajold = 0;
int skvaj1 = 0, skvaj2 = 0;
int bar = 0;
int psi = 0;
float p = 0;

int kanal[6] = {0, 0, 500, 75, 800, 1500};
//режим1, режим2, нач.откр., полн. откр. %, полн. откр., задержка
int dat[6] = {0, 1023, 0, 0, 0, 0};
//знач.0, знач.5, избыток пар., текущее знач., ед. изм.
char buffer[20];

unsigned long skvajtime = 0;
// int skvajtimevalue = 0;

// #define skvajmaxProc 85//procent skvajinnosti maximalnogo znacheniya
// int skvajmax = skvajmaxProc * 255 / 100; //raschet

const int NUM_ITEMS = 5; // number of items in the list and also the number of screenshots and screenshots with QR codes (other screens)
const int MAX_ITEM_LENGTH = 13; // maximum characters for the item name

char menu_items [NUM_ITEMS] [MAX_ITEM_LENGTH] = {  // array with item names
  { "Edinici izm." },
  { "Datchiki" },
  { "Karta #1" },
  { "Kanal PU" },
  { "Vihod" },
};

char menu_ed [NUM_ITEMS] [MAX_ITEM_LENGTH] = {  // array with item names
  { "kPa" },
  { "bar" },
  { "pri" },
  { "%" },
  { "Nazad" },
};

char menu_dat [NUM_ITEMS - 1] [MAX_ITEM_LENGTH] = { // array with item names
  { "0v" },
  { "5v" },
  { "izbitok" },
  { "Nazad" },
};

char menu_karta [NUM_ITEMS] [MAX_ITEM_LENGTH] = { // array with item names
  { "Nach.ot.Z" },
  { "Poln.ot.%" },
  { "Poln.ot.Z" },
  { "Zaderjka" },
  { "Nazad" },
};

char menu_kanal [NUM_ITEMS - 2] [MAX_ITEM_LENGTH] = { // array with item names
  { "Kanal 1" },
  { "Kanal 2" },
  { "Nazad" },
};

int item_selected = 0; // which item in the menu is selected

#include <EEPROM.h>
byte prov = 4;

void setup() {
  Serial.begin(115200);
  // Serial.println("Test");

  display.begin();
  display.setPowerSave(0);
  display.setFont(u8x8_font_pxplusibmcgathin_f);


  if (!bmp.begin()) { // Если датчик BMP280 не найден
    // Serial.println("BMP280 SENSOR ERROR"); // Выводим сообщение об ошибке
    // while (1); // Переходим в бесконечный цикл
  }
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, // Режим работы
                  Adafruit_BMP280::SAMPLING_X2, // Точность изм. температуры
                  Adafruit_BMP280::SAMPLING_X16, // Точность изм. давления
                  Adafruit_BMP280::FILTER_X16, // Уровень фильтрации
                  Adafruit_BMP280::STANDBY_MS_500); // Период просыпания, мСек

  pinMode(M1, OUTPUT);
  pinMode(M2, OUTPUT);
  digitalWrite(M1, LOW);//Mosfet 1
  digitalWrite(M2, LOW);//Mosfet 2

  pinMode(D1, INPUT);

  pinMode(PWR_PIN, INPUT_PULLUP);

  if (EEPROM.read(9) == prov)
  {
    EEPROM.get(10, kanal);
    EEPROM.get(30, dat);
  }
  else {
    EEPROM.put(10, kanal);
    EEPROM.put(30, dat);
  }
}

void loop() {
  if (digitalRead(PWR_PIN)) {
    Triger = 0;
    enc1.tick();

    if (enc1.isRight()) {
      // Serial.println("Right");         // если был поворот
      if (disp == 1 || disp == 2 || disp == 4)
      {
        if (item_selected < NUM_ITEMS - 1)
          item_selected++;
      }
      else if (disp == 3)
      {
        if (item_selected < NUM_ITEMS - 2)
          item_selected++;
      }
      else if (disp == 5)
      {
        if (item_selected < NUM_ITEMS - 3)
          item_selected++;
      }
    }
    if (enc1.isLeft()) {
      // Serial.println("Left");
      if (item_selected > 0)
        item_selected--;
    }

    if (enc1.isRightH()) {
      // Serial.println("Right holded"); // если было удержание + поворот
      if (disp == 4) {
        if (item_selected == 0 && kanal[2] < 1023)
          kanal[2]++;
        if (item_selected == 1 && kanal[3] < 100) {
          kanal[3]++;
          kanal[4] = map(kanal[3], 0, 100, 0, 1023);
        }
        if (item_selected == 2 && kanal[4] < 1023) {
          kanal[4]++;
          kanal[3] = map(kanal[4], 0, 1023, 0, 100);
        }
        if (item_selected == 3 && kanal[5] < 3000)
          kanal[5] = kanal[5] + 500;
      }
    }
    if (enc1.isLeftH()) {
      // Serial.println("Left holded");
      if (disp == 4) {
        if (item_selected == 0 && kanal[2] > 0)
          kanal[2]--;
        if (item_selected == 1 && kanal[3] > 0) {
          kanal[3]--;
          kanal[4] = map(kanal[3], 0, 100, 0, 1023);
        }
        if (item_selected == 2 && kanal[4] > 0) {
          kanal[4]--;
          kanal[3] = map(kanal[4], 0, 1023, 0, 100);
        }
        if (item_selected == 3 && kanal[5] > 0)
          kanal[5] = kanal[5] - 500;
      }
    }

    if (enc1.isClick()) {
      // Serial.println("Click");         // одиночный клик
      if (disp == 1) {
        if (item_selected == 0)
          disp = 2;
        else if (item_selected == 1)
          disp = 3;
        else if (item_selected == 2)
          disp = 4;
        else if (item_selected == 3)
          disp = 5;
        else if (item_selected == 4) {
          disp = 0;
          EEPROM.put(10, kanal);
          EEPROM.put(30, dat);
        }
        item_selected = 0;
        display.clearDisplay();
      }
      else if (disp == 2)
      {
        if (item_selected == 0)
          dat[4] = 0;
        else if (item_selected == 1)
          dat[4] = 1;
        else if (item_selected == 2)
          dat[4] = 2;
        else if (item_selected == 3)
          dat[4] = 3;
        else if (item_selected == 4) {
          disp = 1;
          item_selected = 0;
        }
        display.clearDisplay();
      }
      else if (disp == 3)
      {
        if (item_selected == 0)
          dat[0] = dat[3];
        else if (item_selected == 1)
          dat[1] = dat[3];
        else if (item_selected == 2)
        {
          if (dat[2] == 0)
            dat[2] = 1;
          else
            dat[2] = 0;
        }
        else if (item_selected == 3) {
          disp = 1;
          item_selected = 0;
        }
        display.clearDisplay();
      }
      else if (disp == 3)
      {
        if (item_selected == 4) {
          disp = 1;
          item_selected = 0;
        }
        display.clearDisplay();
      }
      else if (disp == 4)
      {
        if (item_selected == 4) {
          disp = 1;
          item_selected = 0;
        }
        display.clearDisplay();
      }
      else if (disp == 5)
      {
        if (item_selected < 2)
        {
          if (kanal[item_selected] < 2)
            kanal[item_selected]++;
          else
            kanal[item_selected] = 0;
        }
        else if (item_selected == 2) {
          disp = 1;
          item_selected = 0;
        }
        display.clearDisplay();
      }
    }

    if (enc1.isHolded()) {
      // Serial.println("Holded");       // если была удержана и энк не поворачивался
      if (disp == 0) {
        disp = 1;
        item_selected = 0;
      }
      else {
        disp = 0;
        EEPROM.put(10, kanal);
        EEPROM.put(30, dat);
      }
      display.clearDisplay();
    }

    dat[3] = analogRead(D1);
    skvaj = constrain(map(dat[3], 0, 1023, dat[0], dat[1]), 0, dat[1]);
    if (dat[2] == 1) {
      if (millis() - obndat >= obnvalue)
      {
        p = bmp.readPressure();
        p = p * 0.00750062; // Преобразуем Паскали в мм.рт.ст.
        obndat = millis();
      }
      skvaj = constrain(skvaj - p, 0, dat[1]);;
    }
    skvaj1 = skvaj;
    skvaj2 = skvaj;
    if (kanal[0] == 0) {
      if (skvaj1 < kanal[2]) {
        skvaj1 = 0;
        if (skvaj1 <= skvajold && millis() - skvajtime >= kanal[5]) {
          digitalWrite(M1, LOW);
          skvajold = skvaj1;
        }
      }
      else if (kanal[2] <= skvaj1 && skvaj1 < kanal[4])
      {
        if (skvaj1 >= skvajold) {
          analogWrite(M1, map(skvaj1, 0, 1023, 0, 255));
          skvajold = skvaj1;
          skvajtime = millis();
        }
        else if (skvaj1 < skvajold && millis() - skvajtime >= kanal[5]) {
          analogWrite(M1, map(skvaj1, 0, 1023, 0, 255));
          skvajold = skvaj1;
        }
      }
      else if (skvaj1 >= kanal[4])
      {
        analogWrite(M1, map(kanal[4], 0, 1023, 0, 255));
        skvajold = kanal[4];
        skvajtime = millis();
      }
    }
    else if (kanal[0] == 1) {
      digitalWrite(M1, HIGH);
    }
    else if (kanal[0] == 2) {
      digitalWrite(M1, LOW);
    }

    if (kanal[1] == 0) {
      if (skvaj2 < kanal[2]) {
        skvaj2 = 0;
        if (skvaj2 <= skvajold && millis() - skvajtime >= kanal[5]) {
          digitalWrite(M2, LOW);
          skvajold = skvaj2;
        }
      }
      else if (kanal[2] <= skvaj2 && skvaj2 < kanal[4])
      {
        if (skvaj2 >= skvajold) {
          analogWrite(M2, map(skvaj2, 0, 1023, 0, 255));
          skvajold = skvaj2;
          skvajtime = millis();
        }
        else if (skvaj2 < skvajold && millis() - skvajtime >= kanal[5]) {
          analogWrite(M2, map(skvaj2, 0, 1023, 0, 255));
          skvajold = skvaj2;
        }
      }
      else if (skvaj2 >= kanal[4])
      {
        analogWrite(M2, map(kanal[4], 0, 1023, 0, 255));
        skvajold = kanal[4];
        skvajtime = millis();
      }
    }
    else if (kanal[1] == 1) {
      digitalWrite(M2, HIGH);
    }
    else if (kanal[1] == 2) {
      digitalWrite(M2, LOW);
    }

    if (millis() - vivod >= vivodvalue && disp == 0)
    {
      if (disp == 0) {
        // display.setFont(u8x8_font_courB24_3x4_r);
        display.setFont(u8x8_font_courB18_2x3_r);
        if (dat[4] == 0) {
          display.setCursor(5, 1);
          sprintf (buffer, "%03d", map(skvaj, dat[0], dat[1], 0, 400));
          display.print(buffer);
          display.setCursor(5, 4);
          display.print("kPa");
        }
        else if (dat[4] == 1) {
          bar = map(skvaj, dat[0], dat[1], 0, 400);
          display.setCursor(4, 1);
          sprintf (buffer, "%01d.%02d", bar / 100, bar % 100);
          display.print(buffer);
          display.setCursor(5, 4);
          display.print("bar");
        }
        else if (dat[4] == 2) {
          psi = map(skvaj, dat[0], dat[1], 0, 6000);
          display.setCursor(3, 1);
          sprintf (buffer, "%02d.%02d", psi / 100, psi % 100);
          display.print(buffer);
          display.setCursor(5, 4);
          display.print("psi");
        }
        else if (dat[4] == 3) {
          display.setCursor(4, 2);
          sprintf (buffer, "%03d%%", constrain(map(skvaj, dat[0], dat[1], 0, 100), 0, 100));
          display.print(buffer);
        }
      }
      vivod = millis();
    }
    if (millis() - vivodM >= vivodmenu && disp > 0)
    {
      // for (int f = 0; f < 6; f++)
      // {
      //   Serial.print(kanal[f]);
      //   Serial.print(" ");
      // }
      // for (int f = 0; f < 6; f++)
      // {
      //   Serial.print(dat[f]);
      //   Serial.print(" ");
      // }
      // Serial.print(p);
      // Serial.print(" ");
      // Serial.println();
      if (disp == 1) {
        display.setFont(u8x8_font_pxplusibmcgathin_f);
        display.setCursor(6, 0);
        display.print("Menu");
        for (int i = 0; i < NUM_ITEMS; i++) {
          display.drawString(1, i + 1, menu_items[i]);
          display.setCursor(0, i + 1);
          if (i == item_selected)
            display.print(">");
          else
            display.print(" ");
        }
      }
      else if (disp == 2) {
        display.setCursor(4, 0);
        display.print("Ed. izm.");
        for (int i = 0; i < NUM_ITEMS; i++) {
          display.drawString(1, i + 1, menu_ed[i]);
          display.setCursor(0, i + 1);
          if (i == item_selected)
            display.print(">");
          else
            display.print(" ");
          display.setCursor(13, i + 1);
          if (i == dat[4])
            display.print("*");
          else
            display.print(" ");
        }
      }
      else if (disp == 3) {
        display.setCursor(4, 0);
        display.print("Datchik");
        for (int i = 0; i < NUM_ITEMS - 1; i++) {
          display.drawString(1, i + 1, menu_dat[i]);
          display.setCursor(0, i + 1);
          if (i == item_selected)
            display.print(">");
          else
            display.print(" ");
          if (i == 0) {
            display.setCursor(6, i + 1);
            sprintf (buffer, "%4d", dat[0]);
            display.print(buffer);
            display.setCursor(11, i + 1);
            sprintf (buffer, "%4d", dat[3]);
            display.print(buffer);
          }
          if (i == 1) {
            display.setCursor(6, i + 1);
            sprintf (buffer, "%4d", dat[1]);
            display.print(buffer);
            display.setCursor(11, i + 1);
            sprintf (buffer, "%4d", dat[3]);
            display.print(buffer);
          }
          if (i == 2) {
            display.setCursor(12, i + 1);
            if (dat[2] == 0)
              display.print("Net");
            else
              display.print("Da ");
          }
        }
      }
      else if (disp == 4) {
        display.setCursor(4, 0);
        display.print("Karta #1");
        for (int i = 0; i < NUM_ITEMS; i++) {
          display.drawString(1, i + 1, menu_karta[i]);
          display.setCursor(0, i + 1);
          if (i == item_selected)
            display.print(">");
          else
            display.print(" ");
          if (i < 4) {
            display.setCursor(11, i + 1);
            sprintf (buffer, "%4d", kanal[i + 2]);
            display.print(buffer);
          }
        }
      }
      else if (disp == 5) {
        display.setCursor(4, 0);
        display.print("Kanal PU");
        for (int i = 0; i < NUM_ITEMS - 2; i++) {
          display.drawString(1, i + 1, menu_kanal[i]);
          display.setCursor(0, i + 1);
          if (i == item_selected)
            display.print(">");
          else
            display.print(" ");
          if (i < 2) {
            display.setCursor(9, i + 1);
            if (kanal[i] == 0)
              display.print("Karta 1");
            else if (kanal[i] == 1)
              display.print("Otkrit");
            else if (kanal[i] == 2)
              display.print("Zakrit");
          }
        }
      }
      vivodM = millis();
    }
  }
  else if (!digitalRead(PWR_PIN) && Triger == 0)
  {
    display.clearDisplay();
    Triger = 1;
  }
}