/*
  Felipe Teixeira Ruolla - João Vitor Graciano Rondini - 2º ano de Mecatrônica
  Programa/Simulação de um Delivery de Açai

  O programa consiste em uma simulação de um programa de delivery de uma loja de açai, chamada "Açaideria".
  O programa vai te pedir pra escolher um tamanho de copo, tipo, creme, fruta, e extra para o açai. Todos eles
  são escolhidos através dos botões. O programa também pede uma gorjeta opcional, que é definida pelo
  potênciometro, e confirmado pelo botão vermelho.
  Se você apertar a opção do botão vermelho, o led vermelho vai acender; se apertar a opção do botão amarelo,
  o led amarelo vai acender; e o mesmo para o verde. O valor da gorjeta seria, teoricamente, nenhum led para
  valor 0 até 3, led vermelho para valor 3 até 7, led vermelho e amarelo para valor 3 até 13, e todos os leds
  acima do valor 13; o problema principal disso era que era necessário utilizar a função while para fazer
  perfeitamente, porém, isso prejudicava a qualidade da simulação, então foi necessário fazer uma "gambiarra"
  com o if.
  Depois de todas as perguntas terem sido respondidas, ele começará o processo de montagem, demonstrando
  cada etapa através dos leds, e do oled através do uso de string. No final, os leds piscam para anunciar
  que o pedido está pronto.
  A última etapa do programa é a conta, mostrando o preço do açai, com base no tamanho, mais a gorjeta. Ele
  também oferece mais algumas informações adicionais, como o tempo que irá levar.
  Se quiser pedir outro açai, é necessário repetir o programa, apertando o botão vermelho. Isso vai fazer
  com que o programa volte ao estado inicial dele.
*/

//bibliotecas
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_I2CDevice.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ezButton.h>
#include <WiFi.h>
#include "PubSubClient.h"

//oled
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

//ezbutton
//se um botão não funcionar, espere 1 segundo e então clique nele novamente
//os botões estão com algum erro de leitura (ezbutton?)
//se clicar 3 vezes e não passar, dê reload na página
ezButton botaovermelho(2); //botão vermelho
ezButton botaoamarelo(4); //botão amarelo
ezButton botaoverde(5); //botão verde

//variaveis
unsigned long tempo = millis();
int adc, gjr_potenciometro, pagina, estado, port = 1883;
float potencia, gorjeta;
String tamanho, tipo, extra, creme, fruta, stMac;
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqttServer = "broker.hivemq.com";
char mac[50];
char clientId[50];

WiFiClient espClient;
PubSubClient client(espClient);

//pinos dos led
#define led_verde 14
#define led_amarelo 12
#define led_vermelho 13

//delay de 1 segundo
void um() {
  tempo = millis();
  while (millis() < tempo + 1000) {
    continue;
  }
}

//delay de 3 segundos
void tres() {
  tempo = millis();
  while (millis() < tempo + 3000) {
    continue;
  }
}

//wifi
void wifiConnect() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
}

//mqtt
void mqttReconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    long r = random(1000);
    sprintf(clientId, "clientId-%ld", r);
    if (client.connect(clientId)) {
      Serial.print(clientId);
      Serial.println(" connected");
      client.subscribe("FelEJot/trab");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

//void setup
void setup() {
  Serial.begin(115200);
  randomSeed(analogRead(0));

  pinMode(led_vermelho, OUTPUT);
  pinMode(led_amarelo, OUTPUT);
  pinMode(led_verde, OUTPUT);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  wifiConnect();
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.macAddress());
  stMac = WiFi.macAddress();
  stMac.replace(":", "_");
  Serial.println(stMac);
  client.setServer(mqttServer, port);

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(20, 10);
  display.println("Forno");
  display.setCursor(20, 30);
  display.println("Automatico");
  display.display();
  tres();  //delay 3s
  tres();  //delay 3s
  // no total, delay de 6 segundos
  display.stopscroll();
  estado = 0;
}

//void loop
void loop() {
  botaovermelho.loop();
  botaoamarelo.loop();
  botaoverde.loop();
  delay(10);
  if (!client.connected()) {
    mqttReconnect();
  }

  switch (estado) {
    case 0: tamanho_acai(); break;
    case 1: tipo_acai(); break;
    case 2: adicional(); break;
    case 6: rs_gorjeta(); break;  //o case 6 fica antes do 5 na programacão, mas na execução o 5 vem antes
    case 5: gorjeta_acai(); break;
    case 7: colocando_opc(); break;
    case 8: finalizacao1(); break;
    case 9: finalizacao2(); break;
    case 99: resetar(); break;
  } //switch
} //loop

//pergunta 0 - tamanho do açai
void tamanho_acai() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 10);
  display.println("Tamanho do acai:");
  display.setCursor(10, 20);
  display.println("330ml (verde)");
  display.setCursor(10, 30);
  display.println("550ml (amarelo)");
  display.setCursor(10, 40);
  display.println("770ml (vermelho)");
  display.display();

  if (botaoverde.isReleased()) {
    tamanho = "330ml";
    analogWrite(led_verde, HIGH);
    um();
    analogWrite(led_verde, LOW);
    estado = 1;
  }

  if (botaoamarelo.isReleased()) {
    tamanho = "550ml";
    analogWrite(led_amarelo, HIGH);
    um();
    analogWrite(led_amarelo, LOW);
    estado = 1;
  }

  if (botaovermelho.isReleased()) {
    tamanho = "770ml";
    analogWrite(led_vermelho, HIGH);
    um();
    analogWrite(led_vermelho, LOW);
    estado = 1;
  }
}

//pergunta 1 - sabor do açai
void tipo_acai() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 10);
  display.println("Tipo de acai:");
  display.setCursor(10, 20);
  display.println("Natural (verde)");
  display.setCursor(10, 30);
  display.println("Nutella (amarelo)");
  display.setCursor(10, 40);
  display.println("Morango (vermelho)");
  display.display();

  if (botaoverde.isReleased()) {
    tipo = "Natural";
    analogWrite(led_verde, HIGH);
    um();
    analogWrite(led_verde, LOW);
    estado = 2;
  }

  if (botaoamarelo.isReleased()) {
    tipo = "com Nutella";
    analogWrite(led_amarelo, HIGH);
    um();
    analogWrite(led_amarelo, LOW);
    estado = 2;
  }

  if (botaovermelho.isReleased()) {
    tipo = "com Morango";
    analogWrite(led_vermelho, HIGH);
    um();
    analogWrite(led_vermelho, LOW);
    estado = 2;
  }
}

//pergunta 2 - adicionais no acai
void adicional() {
  if (botaoverde.isReleased()) {
    pagina++;
  }
  if (botaoamarelo.isReleased()) {
    estado = 3;
  }
  if (pagina > 3 || pagina < 0) {
    pagina = 0;
  }

  for (int adc = 0; adc < 4; adc++) {
    switch (pagina) {
      case 0:
        display.clearDisplay();
        display.setTextSize(1);
        display.setTextColor(WHITE);
        display.setCursor(10, 10);
        display.println("Adicionais do Acai");
        display.setCursor(10, 20);
        display.println("(Escolha 3)");
        display.setCursor(10, 30);
        display.println("Verde = Prox. Pag");
        display.setCursor(10, 40);
        display.println("Amarelo = Enter");
        display.setCursor(10, 50);
        display.println("Selec. = Potenciomet.");
        display.setCursor(60, 60);
        display.println(adc);
        display.setCursor(90, 60);
        display.println("0/3");
        display.display();
        if (botaovermelho.isReleased()) {
          pagina = 1;
        }
        break;

      case 1:
        display.clearDisplay();
        display.setTextSize(1);
        display.setTextColor(WHITE);
        display.setCursor(10, 10);
        display.println("Adicionais");
        display.setCursor(10, 20);
        display.println("Granola");
        display.setCursor(10, 20);
        display.println("Ninho em Po");
        display.setCursor(10, 30);
        display.println("Nutella");
        display.setCursor(10, 40);
        display.println("Oreo");
        display.setCursor(60, 60);
        display.println(adc);
        display.setCursor(90, 60);
        display.println("1/3");
        display.display();
        if (botaovermelho.isReleased()) {
          pagina = 2;
        }
        break;

      case 2:
        display.clearDisplay();
        display.setTextSize(1);
        display.setTextColor(WHITE);
        display.setCursor(10, 10);
        display.println("Adicionais");
        display.setCursor(10, 20);
        display.println("Kiwi");
        display.setCursor(10, 20);
        display.println("Morango");
        display.setCursor(10, 30);
        display.println("Uva");
        display.setCursor(10, 40);
        display.println("Banana");
        display.setCursor(60, 60);
        display.println(adc);
        display.setCursor(90, 60);
        display.println("2/3");
        display.display();
        if (botaovermelho.isReleased()) {
          pagina = 3;
        }
        break;

      case 3:
        display.clearDisplay();
        display.setTextSize(1);
        display.setTextColor(WHITE);
        display.setCursor(10, 10);
        display.println("Adicionais");
        display.setCursor(10, 20);
        display.println("Bis Black");
        display.setCursor(10, 20);
        display.println("Kit Kat");
        display.setCursor(10, 30);
        display.println("Ovomaltine");
        display.setCursor(10, 40);
        display.println("Trento");
        display.setCursor(60, 60);
        display.println(adc);
        display.setCursor(90, 60);
        display.println("3/3");
        display.display();
        if (botaovermelho.isReleased()) {
          pagina = 0;
        }
        break;

    } //switch
  } //for
  estado = 3;
} //


































// valor da gorjeta - vem do case 5 pra cá
void rs_gorjeta() {
  display.clearDisplay();
  potencia = analogRead(gjr_potenciometro);
  gorjeta = (15 * potencia) / 4095;
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 10);
  display.println("Gorjeta em RS:");
  display.setCursor(10, 20);
  display.println(gorjeta);
  display.setCursor(10, 30);
  display.println("Confirme com o");
  display.setCursor(10, 40);
  display.println("botao vermelho");
  display.display();

  /*
    while (gorjeta > 2) {
    analogWrite(led_vermelho, HIGH); }
    while (gorjeta > 8) {
    analogWrite(led_amarelo, HIGH); }
    while (gorjeta < 14) {
    analogWrite(led_verde, HIGH); }

    se usar while ao inves de if, a simulacao cai de 97% pra 13%
  */

  if (gorjeta == 0) {
    analogWrite(led_vermelho, LOW);
    analogWrite(led_amarelo, LOW);
    analogWrite(led_verde, LOW);
  }

  if (gorjeta >= 3) {
    analogWrite(led_vermelho, HIGH);
    analogWrite(led_amarelo, LOW);
    analogWrite(led_verde, LOW);
  }

  if (gorjeta >= 7) {
    analogWrite(led_vermelho, HIGH);
    analogWrite(led_amarelo, HIGH);
    analogWrite(led_verde, LOW);
  }

  if (gorjeta >= 13) {
    analogWrite(led_vermelho, HIGH);
    analogWrite(led_amarelo, HIGH);
    analogWrite(led_verde, HIGH);
  }

  if (botaovermelho.isReleased()) {
    analogWrite(led_vermelho, LOW);
    analogWrite(led_amarelo, LOW);
    analogWrite(led_verde, LOW);
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(10, 20);
    display.println("Obrigado!");
    display.display();
    tres();
    estado = 7;
  }
}

//pergunta 5 - vai dar gorjeta?
void gorjeta_acai() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 10);
  display.println("Gorjetinha?");
  display.setCursor(10, 30);
  display.println("Utilize o");
  display.setCursor(10, 40);
  display.println("Potenciometro");
  display.display();
  tres();
  estado = 6;
}

//operacao - colocando as coisas no acai
void colocando_opc() {

  //tamanho do acai
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 20);
  display.println("Pegando o copo");
  display.setCursor(10, 30);
  display.println("de " + tamanho);
  display.display();
  analogWrite(led_vermelho, HIGH);
  tres();

  //sabor do acai
  display.clearDisplay();
  display.setCursor(10, 20);
  display.println("Colocando no copo:");
  display.setCursor(10, 30);
  display.println("Acai " + tipo);
  display.display();
  analogWrite(led_amarelo, HIGH);
  tres();

  //creme no acai
  display.clearDisplay();
  display.setCursor(10, 20);
  display.println("Colocando no copo:");
  display.setCursor(10, 30);
  display.println("Creme de " + creme);
  display.display();
  analogWrite(led_verde, HIGH);
  tres();

  analogWrite(led_vermelho, LOW);
  analogWrite(led_amarelo, LOW);
  analogWrite(led_verde, LOW);

  //fruta no acai
  display.clearDisplay();
  display.setCursor(10, 20);
  display.println("Colocando no copo:");
  display.setCursor(10, 30);
  display.println("Pedacos de " + fruta);
  display.display();
  analogWrite(led_vermelho, HIGH);
  tres();

  //extra no acai
  display.clearDisplay();
  display.setCursor(10, 20);
  display.println("Colocando no copo:");
  display.setCursor(10, 30);
  display.println("Extra " + extra);
  display.display();
  analogWrite(led_amarelo, HIGH);
  tres();

  //gorjeta
  display.clearDisplay();
  display.setCursor(10, 20);
  display.println("Adicionando gorjeta");
  display.setCursor(10, 30);
  display.println("De");
  display.setCursor(30, 30);
  display.println(gorjeta);
  display.setCursor(70, 30);
  display.println("na conta");
  display.display();
  analogWrite(led_verde, HIGH);
  tres();

  display.clearDisplay();
  analogWrite(led_vermelho, LOW);
  analogWrite(led_amarelo, LOW);
  analogWrite(led_verde, LOW);
  estado = 8;
}

//finalizacao1 - agradecimento / acai finalizado
void finalizacao1() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 20);
  display.println("Acai finalizado!");
  display.setCursor(10, 30);
  display.println("Obrigado por pedir!");
  display.display();

  um();
  analogWrite(led_vermelho, HIGH);
  analogWrite(led_amarelo, HIGH);
  analogWrite(led_verde, HIGH);
  um();
  analogWrite(led_vermelho, LOW);
  analogWrite(led_amarelo, LOW);
  analogWrite(led_verde, LOW);
  um();
  analogWrite(led_vermelho, HIGH);
  analogWrite(led_amarelo, HIGH);
  analogWrite(led_verde, HIGH);
  um();
  analogWrite(led_vermelho, LOW);
  analogWrite(led_amarelo, LOW);
  analogWrite(led_verde, LOW);
  um();
  analogWrite(led_vermelho, HIGH);
  analogWrite(led_amarelo, HIGH);
  analogWrite(led_verde, HIGH);
  um();
  analogWrite(led_vermelho, LOW);
  analogWrite(led_amarelo, LOW);
  analogWrite(led_verde, LOW);
  um();

  display.clearDisplay();
  estado = 9;
}

//finalizacao2 - valor do acai
void finalizacao2() {
  if (tamanho == "330ml") {
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(10, 10);
    display.println("O valor foi de");
    display.setCursor(10, 20);
    display.println("RS 20,00 + ");
    display.setCursor(10, 30);
    display.println("RS");
    display.setCursor(30, 30);
    display.println(gorjeta);
    display.setCursor(60, 30);
    display.println(" de gorjeta");
    display.display();
  }

  if (tamanho == "550ml") {
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(10, 10);
    display.println("O valor foi de");
    display.setCursor(10, 20);
    display.println("RS 25,00 + ");
    display.setCursor(10, 30);
    display.println("RS");
    display.setCursor(30, 30);
    display.println(gorjeta);
    display.setCursor(60, 30);
    display.println(" de gorjeta");
    display.display();
  }

  if (tamanho == "770ml") {
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(10, 10);
    display.println("O valor foi de");
    display.setCursor(10, 20);
    display.println("RS 30,00 + ");
    display.setCursor(10, 30);
    display.println("RS");
    display.setCursor(30, 30);
    display.println(gorjeta);
    display.setCursor(60, 30);
    display.println(" de gorjeta");
    display.display();
  }

  tres();
  um();
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 10);
  display.println("O pedido chegara na");
  display.setCursor(10, 20);
  display.println("localizacao do seu");
  display.setCursor(10, 30);
  display.println("dispositivo entre");
  display.setCursor(10, 40);
  display.println("30 a 50 minutos");
  display.display();
  display.clearDisplay();
  tres();
  tres();
  display.setCursor(10, 20);
  display.println("O pagamento sera");
  display.setCursor(10, 30);
  display.println("feito na entrega");
  display.display();
  display.clearDisplay();
  tres();
  display.setCursor(10, 10);
  display.println("Obrigado pela");
  display.setCursor(10, 20);
  display.println("preferencia!!!");
  display.setCursor(10, 40);
  display.println("Volte sempre!");
  display.display();
  tres();
  tres();

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 10);
  display.println("Se quiser pedir");
  display.setCursor(10, 20);
  display.println("novamente, apenas");
  display.setCursor(10, 30);
  display.println("resete o programa");
  display.setCursor(10, 40);
  display.println("(botao vermelho)");
  display.display();
  estado = 99; //reset
}

void resetar() {
  if (botaovermelho.isReleased()) {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(20, 10);
    display.println("Reiniciando");
    display.display();
    tres();
    display.clearDisplay();
    display.setCursor(20, 10);
    display.println("Reiniciando.");
    display.display();
    tres();
    display.clearDisplay();
    display.setCursor(20, 10);
    display.println("Reiniciando..");
    display.display();
    tres();
    display.clearDisplay();
    display.setCursor(20, 10);
    display.println("Reiniciando...");
    display.display();
    tres();
    display.clearDisplay();
    estado = 1;
  }
}