
// https://circuits4you.com/2019/01/11/nodemcu-esp8266-arduino-json-parsing-example/

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
#include <LiquidCrystal_I2C.h>
#include <WiFiUdp.h>
#include <NTPClient.h>

// ================= NTP =================

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");

// ================= WIFI =================

const char* SSID = "IFSC";
const char* PASSWORD = "campuschapeco";

// ================= LCD =================

LiquidCrystal_I2C lcd(0x27, 16, 2);

// ================= URL =================

String BASE_URL = "http://www.projeto8.migueldebarba.com.br/bruno/testejson.php";

// ================= LED RGB =================

#define ledR 14
#define ledG 12
#define ledB 15

// ================= VARIAVEIS =================

String payload;
String linhaum, linhadois;
String currentDate;

int diai = 0;
int mesi = 0;
int anoi = 0;

int diaf = 0;
int mesf = 0;
int anof = 0;

// ================= DIAS E MESES =================

String weekDays[7] = {
  "Domingo",
  "Segunda",
  "Terca",
  "Quarta",
  "Quinta",
  "Sexta",
  "Sabado"
};

String months[12] = {
  "Janeiro",
  "Fevereiro",
  "Marco",
  "Abril",
  "Maio",
  "Junho",
  "Julho",
  "Agosto",
  "Setembro",
  "Outubro",
  "Novembro",
  "Dezembro"
};

// ================= OBJETOS =================

WiFiClient client;
HTTPClient http;

// ======================================================
// FUNCAO HORA
// ======================================================

void pegahora() {

  timeClient.update();

  time_t epochTime = timeClient.getEpochTime();

  Serial.print("Epoch Time: ");
  Serial.println(epochTime);

  String formattedTime = timeClient.getFormattedTime();

  Serial.print("Formatted Time: ");
  Serial.println(formattedTime);

  int currentHour = timeClient.getHours();

  Serial.print("Hour: ");
  Serial.print(currentHour);

  int currentMinute = timeClient.getMinutes();

  Serial.print(" - Minutes: ");
  Serial.print(currentMinute);

  int currentSecond = timeClient.getSeconds();

  Serial.print(" - Seconds: ");
  Serial.println(currentSecond);

  String weekDay = weekDays[timeClient.getDay()];

  Serial.print("Week Day: ");
  Serial.println(weekDay);

  struct tm *ptm = gmtime((time_t *)&epochTime);

  int monthDay = ptm->tm_mday;

  Serial.print("Month day: ");
  Serial.print(monthDay);

  int currentMonth = ptm->tm_mon + 1;

  Serial.print(" - Month: ");
  Serial.print(currentMonth);

  String currentMonthName = months[currentMonth - 1];

  Serial.print(" - Month name: ");
  Serial.println(currentMonthName);

  int currentYear = ptm->tm_year + 1900;

  Serial.print("Year: ");
  Serial.println(currentYear);

  currentDate = String(currentYear) + "-" +
                String(currentMonth) + "-" +
                String(monthDay);

  Serial.print("Current date: ");
  Serial.println(currentDate);
}

// ======================================================
// SERIAL
// ======================================================

void initSerial() {
  Serial.begin(115200);
}

// ======================================================
// WIFI
// ======================================================

void initWiFi() {

  delay(10);

  Serial.println();
  Serial.println("Conectando-se em: " + String(SSID));

  WiFi.begin(SSID, PASSWORD);

  while (WiFi.status() != WL_CONNECTED) {

    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.print("Conectado na rede ");
  Serial.print(SSID);
  Serial.print(" | IP => ");
  Serial.println(WiFi.localIP());

  lcd.setCursor(0, 0);
  lcd.print(SSID);

  lcd.setCursor(0, 1);
  lcd.print(WiFi.localIP());

  delay(2000);
  lcd.clear();
}

// ======================================================
// HTTP REQUEST
// ======================================================

String makeRequest() {

  http.begin(client, BASE_URL);

  int httpCode = http.GET();

  if (httpCode > 0) {

    if (httpCode == HTTP_CODE_OK) {

      String response = http.getString();

      http.end();

      return response;
    }
  }

  Serial.print("Erro HTTP: ");
  Serial.println(httpCode);

  http.end();

  return "";
}

void httpRequest() {

  payload = makeRequest();

  if (payload.length() == 0) {

    Serial.println("Payload vazio");
  }
}

// ======================================================
// LCD SCROLL
// ======================================================

void showLetters(int printStart, int startLetter) {

  lcd.clear();

  lcd.setCursor(printStart, 0);

  for (int currentLetter = startLetter;
       currentLetter < linhaum.length();
       currentLetter++) {

    lcd.print(linhaum[currentLetter]);
  }

  lcd.print(" ");

  lcd.setCursor(printStart, 1);

  for (int currentLetter = startLetter;
       currentLetter < linhadois.length();
       currentLetter++) {

    lcd.print(linhadois[currentLetter]);
  }

  lcd.print(" ");

  delay(250);
}

// ======================================================
// SETUP
// ======================================================

void setup() {

  pinMode(ledR, OUTPUT);
  pinMode(ledG, OUTPUT);
  pinMode(ledB, OUTPUT);

  initSerial();

  lcd.init();
  lcd.setBacklight(HIGH);

  initWiFi();

  // NTP
  timeClient.begin();

  // Brasil UTC-3
  timeClient.setTimeOffset(-10800);
}

// ======================================================
// LOOP
// ======================================================

void loop() {

  Serial.println();
  Serial.println("[GET] /testejson.php");
  Serial.println();

  httpRequest();

  Serial.println("payload:");
  Serial.println(payload);

  if (payload.length() == 0) {

    delay(5000);
    return;
  }

  // Buffer JSON
  StaticJsonDocument<512> doc;

  // Desserializa
  DeserializationError error = deserializeJson(doc, payload);

  if (error) {

    Serial.print("Erro JSON: ");
    Serial.println(error.f_str());

    delay(5000);
    return;
  }

  // Primeiro elemento do array
  JsonObject painel = doc[0];

  // ================= CAMPOS =================

  int idpainel = painel["idpainel"] | 0;

  const char* mac = painel["mac_idmac"] | "";

  const char* nome = painel["nome"] | "";

  int ledr = painel["ledr"] | 0;
  int ledg = painel["ledg"] | 0;
  int ledb = painel["ledb"] | 0;

  linhaum = painel["linhaum"] | "";
  linhadois = painel["linhadois"] | "";

  String datainicial = "";
  String datafinal = "";

  if (!painel["datainicial"].isNull()) {

    datainicial = painel["datainicial"].as<String>();
  }

  if (!painel["datafinal"].isNull()) {

    datafinal = painel["datafinal"].as<String>();
  }

  // ================= LCD =================

  int t1 = linhaum.length();

  for (int letter = 0; letter <= t1; letter++) {

    showLetters(0, letter);
  }

  // ================= LED RGB =================

  analogWrite(ledR, ledr);
  analogWrite(ledG, ledg);
  analogWrite(ledB, ledb);

  // ================= SERIAL =================

  Serial.println();
  Serial.println("=== Dados do Painel ===");

  Serial.print("ID: ");
  Serial.println(idpainel);

  Serial.print("MAC: ");
  Serial.println(mac);

  Serial.print("Nome: ");
  Serial.println(nome);

  Serial.print("LED R: ");
  Serial.println(ledr);

  Serial.print("LED G: ");
  Serial.println(ledg);

  Serial.print("LED B: ");
  Serial.println(ledb);

  Serial.print("Linha UM: ");
  Serial.println(linhaum);

  Serial.print("Linha DOIS: ");
  Serial.println(linhadois);

  // ================= DATA INICIAL =================

  Serial.print("Data inicial: ");
  Serial.println(datainicial);

  if (datainicial.length() > 0) {

    sscanf(datainicial.c_str(),
           "%d/%d/%d",
           &diai,
           &mesi,
           &anoi);

    Serial.print("Dia: ");
    Serial.print(diai);

    Serial.print(" Mes: ");
    Serial.print(mesi);

    Serial.print(" Ano: ");
    Serial.println(anoi);
  }
  else {

    Serial.println("Data inicial vazia");
  }

  // ================= DATA FINAL =================

  Serial.print("Data final: ");
  Serial.println(datafinal);

  if (datafinal.length() > 0) {

    sscanf(datafinal.c_str(),
           "%d/%d/%d",
           &diaf,
           &mesf,
           &anof);

    Serial.print("Dia final: ");
    Serial.print(diaf);

    Serial.print(" Mes final: ");
    Serial.print(mesf);

    Serial.print(" Ano final: ");
    Serial.println(anof);
  }
  else {

    Serial.println("Data final vazia");
  }

  // ================= HORA =================

  pegahora();

  Serial.print("Server date: ");
  Serial.println(currentDate);

  delay(5000);
}