// SCREEN
////////////////////////////////////////////////////////////////////////////////////////////
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
const int bit16Colors[8] = {0xFFFF,0xF800,0x07E0,0x001F,0x07FF,0xF81F,0xFFE0,0xFC00};
void screenBottomLogo()
{
  tft.fillRect(0,110,240,135,ST77XX_BLACK);
  for (int i=0;i<8;i+=1){tft.drawLine(30*i,110,30*(i+1),110,bit16Colors[i]);}
  tft.setTextColor(ST77XX_WHITE);  
  tft.setCursor(5, 120);
  tft.print("clinc");  
  tft.setCursor(0,0);
}
void screenNewMsg(const char *text)
{
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(ST77XX_WHITE);
  tft.print(text);
}

// WIFI
////////////////////////////////////////////////////////////////////////////////////////////
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid     = "your_ssid";
const char* password = "your_pwd";
#include <ESPAsyncWebServer.h>
AsyncWebServer server(80);

// AUDIO
////////////////////////////////////////////////////////////////////////////////////////////
#include "Arduino.h"
#include "Audio.h"
#define I2S_DOUT  39
#define I2S_BCLK  38
#define I2S_LRC   37
#define VMLED  8
#define VMB 14
char voicemail[128]="Mr and Mrs Dursley of number four, Privet Drive, were proud to say that they were perfectly normal, thank you very much";
Audio audio;

class Button {
  public:
    int numberpin;bool ispressed = false;
    Button (int pin){numberpin = pin;}
    virtual void onPressDown(){} virtual void onPressUp(){}
    void listen()
    {
      int buttonState = digitalRead(numberpin);
      if (buttonState == 1){if (!ispressed){onPressDown();ispressed=true;}}
      else{if (ispressed){onPressUp();ispressed=false;}}
    }
};

class PingBackend : public Button {
  public:
  PingBackend(int pin) : Button(pin) {}
  /*add custom method*/
  void onPressUp( ) override{ apiPayLoad("http://172.16.0.0:5000/esp32Ping");delay(100);}
};

class ClearScreen : public Button {
  public:
  ClearScreen(int pin) : Button(pin) {}
  /*add custom method*/
  void onPressUp( ) override{tft.fillScreen(ST77XX_BLACK);digitalWrite(TFT_BACKLITE, LOW);delay(100);}
};

class CheckVoiceMail : public Button {
  public:
  CheckVoiceMail(int pin) : Button(pin) {}
  /*add custom method*/
  void onPressUp( ) override{ 
    digitalWrite(VMLED, LOW);digitalWrite(TFT_BACKLITE, HIGH);
    screenNewMsg(voicemail);screenBottomLogo();
    audio.connecttospeech(voicemail,"en");delay(100);
  }
};

void apiPayLoad(String url)
{
  HTTPClient http;http.begin(url);int httpCode = http.GET();
  if(httpCode == HTTP_CODE_OK) 
  {
    String payload = http.getString();
    audio.connecttospeech("ping","en");
    digitalWrite(TFT_BACKLITE, HIGH);
    screenNewMsg("PING http://172.16.0.0:5000");
    screenBottomLogo();
  }  
}

PingBackend pingBackend(1);
ClearScreen clearScreen(2);
CheckVoiceMail checkVM(VMB);

void setup() {

  Serial.begin(115200);
  pinMode(1, INPUT_PULLDOWN);
  pinMode(2, INPUT_PULLDOWN);
  pinMode(VMB, INPUT_PULLUP);
  pinMode(VMLED, OUTPUT);

  // SCREEN
  ////////////////////////////////////////////////////////////////////////////////////////////
  pinMode(TFT_BACKLITE, OUTPUT);
  digitalWrite(TFT_BACKLITE, HIGH);
  pinMode(TFT_I2C_POWER, OUTPUT);
  digitalWrite(TFT_I2C_POWER, HIGH);
  delay(10);
  tft.init(135, 240);
  tft.setRotation(3);
  tft.fillScreen(ST77XX_BLACK);
  tft.setTextSize(2);
  delay(1000);

  // AUDIO
  ////////////////////////////////////////////////////////////////////////////////////////////
  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  audio.setVolume(15); // 0 <> 21

  // WIFI INIT
  ////////////////////////////////////////////////////////////////////////////////////////////
  WiFi.begin(ssid, password);
  // Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    // Serial.print(".");
  }
  // Serial.println("");
  // Serial.print("Connected to WiFi network with IP Address: ");
  // Serial.println(WiFi.localIP());
  screenNewMsg(WiFi.localIP().toString().c_str());   
  screenBottomLogo();


  // MAIN API
  ////////////////////////////////////////////////////////////////////////////////////////////
  DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); 
  server.on("/action", HTTP_POST, [](AsyncWebServerRequest *request) {
    // Serial.println("ACTION!");
    int params = request->params();
    for(int i=0;i<params;i++){
      const AsyncWebParameter* p = request->getParam(i);
      // Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
      digitalWrite(VMLED, HIGH);
      const char * msg = p->value().c_str();
      strcpy(voicemail, msg);
      digitalWrite(TFT_BACKLITE, HIGH);
      screenNewMsg(voicemail);
      screenBottomLogo();
      audio.connecttospeech(voicemail,"en");
    }
    request->send(200);
  });
  server.begin();
}

void loop() {
  audio.loop();
  pingBackend.listen();
  clearScreen.listen();
  checkVM.listen();
}
