#define BLYNK_PRINT Serial
#define BLYNK_TEMPLATE_ID "TMPL2TbG1EPUc"
#define BLYNK_TEMPLATE_NAME "Feedback Machine"
#define BLYNK_AUTH_TOKEN "X0ZcPLZjfDvRN1SsEFzvfGG91iKy4mlQ"

#include <BlynkSimpleEsp32.h>
#include <LiquidCrystal_I2C.h>

#include <Preferences.h>
#include  "Wire.h"

#define GOOD 14
#define OK 27
#define BAD 26

LiquidCrystal_I2C lcd(0x27, 20, 4); 

#define SSID "Wokwi-GUEST"
#define PASSWORD ""

String question = "Generic Question";

int positiveFeedback = 0;
int negativeFeedback = 0;

bool blynkConnected = false;

Preferences preferences;


void setup() {

  pinMode(BAD, INPUT_PULLUP);
  pinMode(OK, INPUT_PULLUP);
  pinMode(GOOD, INPUT_PULLUP);

  Serial.begin(115200);

  preferences.begin("feedback", false); 

  lcd.init();


  lcd.print("Connecting to WIFI");

  Blynk.begin(BLYNK_AUTH_TOKEN, SSID, PASSWORD);


  while (!blynkConnected) {
    delay(100);
  }

  lcd.setCursor(0,0);
  lcd.print("Initializing Data  ");

  preferences.putInt("bad", 0);
  preferences.putInt("ok", 0);
  preferences.putInt("good", 0);

}

void loop() {
  //wait  for a second
  while (true) {
    delay(10);
    if (digitalRead(GOOD) == LOW) {
      preferences.putInt("good", preferences.getInt("good") + 1);
      Blynk.virtualWrite(V0, preferences.getInt("good"));
      break;
    } else if (digitalRead(OK) == LOW) {
      preferences.putInt("ok", preferences.getInt("ok") + 1);
      Blynk.virtualWrite(V1, preferences.getInt("ok"));
      break;
    } else if (digitalRead(BAD) == LOW) {
      preferences.putInt("bad", preferences.getInt("bad") + 1);
      Blynk.virtualWrite(V2, preferences.getInt("bad"));  //! fix this duplication later
      break;
    }
    Blynk.run();
  }
  // tell the screen to write on the top row
  lcd.setCursor(0,3);
  lcd.print("Feedback sent!");
  delay(1000);
  lcd.setCursor(0,3);
  lcd.print("              ");
}

BLYNK_CONNECTED()
{
    blynkConnected = true;
    Blynk.syncVirtual(V10);
}

BLYNK_WRITE(V10) {
  lcd.clear();
  String newQuestion = param.asString();

  if (newQuestion.length() > 20) {
    lcd.print(newQuestion.substring(0, 20));
    lcd.setCursor(0,1);
    lcd.print(newQuestion.substring(20));
  } else {
    lcd.println(newQuestion);
  }

  if (!blynkConnected) {
    return;
  }
  preferences.putInt("bad", 0);
  preferences.putInt("ok", 0);
  preferences.putInt("good", 0);
  Blynk.virtualWrite(V0, 0);
  Blynk.virtualWrite(V1, 0);
  Blynk.virtualWrite(V2, 0);
}

#define BLYNK_TEMPLATE_ID "TMPL2TbG1EPUc"
#define BLYNK_TEMPLATE_NAME "Feedback Machine"
#define BLYNK_AUTH_TOKEN "X0ZcPLZjfDvRN1SsEFzvfGG91iKy4mlQ"

#include <BlynkSimpleEsp32.h>
#include <GxEPD2_BW.h>
#include <Fonts/FreeMonoBold24pt7b.h>

#include <Preferences.h>
#include  "Wire.h"

#define GOOD 14
#define OK 27
#define BAD 26

GxEPD2_BW<GxEPD2_750_T7, GxEPD2_750_T7::HEIGHT> display(GxEPD2_750_T7(/*CS=5*/ 5, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));

#define SSID "Wokwi-GUEST"
#define PASSWORD ""

String question = "Generic Question";

int positiveFeedback = 0;
int negativeFeedback = 0;

bool blynkConnected = false;

Preferences preferences;


void setup() {

  pinMode(BAD, INPUT_PULLUP);
  pinMode(OK, INPUT_PULLUP);
  pinMode(GOOD, INPUT_PULLUP);

  Serial.begin(115200);

  preferences.begin("feedback", false); 

  display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse

  updateMessage("Initializing...");

  Blynk.begin(BLYNK_AUTH_TOKEN, SSID, PASSWORD);

  preferences.putInt("bad", 0);
  preferences.putInt("ok", 0);
  preferences.putInt("good", 0);

}

void loop() {
  //wait  for a second
  while (true) {
    delay(10);
    if (digitalRead(GOOD) == LOW) {
      preferences.putInt("good", preferences.getInt("good") + 1);
      Blynk.virtualWrite(V0, preferences.getInt("good"));
      break;
    } else if (digitalRead(OK) == LOW) {
      preferences.putInt("ok", preferences.getInt("ok") + 1);
      Blynk.virtualWrite(V1, preferences.getInt("ok"));
      break;
    } else if (digitalRead(BAD) == LOW) {
      preferences.putInt("bad", preferences.getInt("bad") + 1);
      Blynk.virtualWrite(V2, preferences.getInt("bad"));  //! fix this duplication later
      break;
    }
    Blynk.run();
  }
  delay(1000);
}

void updateMessage(const char text[])
{
  display.setRotation(0);
  display.setFont(&FreeMonoBold24pt7b);
  display.setTextColor(GxEPD_BLACK);
  int16_t tbx, tby; uint16_t tbw, tbh;
  display.getTextBounds(text, 0, 0, &tbx, &tby, &tbw, &tbh);
  // center the bounding box by transposition of the origin:
  uint16_t x = ((display.width() - tbw) / 2) - tbx;
  uint16_t y = ((display.height() - tbh) / 2) - tby;
  display.setFullWindow();
  display.firstPage();
  do
  {
    display.fillScreen(GxEPD_WHITE);
    display.setCursor(x, y);
    display.print(text);
  }
  while (display.nextPage());
}

BLYNK_CONNECTED()
{
    blynkConnected = true;
    Blynk.syncVirtual(V10);
}

BLYNK_WRITE(V10) {
  updateMessage(param.asStr());
  display.hibernate();

  if (!blynkConnected) {
    return;
  }
  preferences.putInt("bad", 0);
  preferences.putInt("ok", 0);
  preferences.putInt("good", 0);
  Blynk.virtualWrite(V0, 0);
  Blynk.virtualWrite(V1, 0);
  Blynk.virtualWrite(V2, 0);
}