/*
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 estado, port = 1883;
float gorjeta, potencia, potenciometro;
String tamanho, tipo, extra, creme, fruta, stMac, stMessage;
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; }
}

//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 (;;);
  }

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.startscrollleft(0x00, 0x0f); // Movimenta texto para a esquerda
  display.setCursor(20, 10);
  display.println("Bem - Vindo");
  display.setCursor(20, 30);
  display.println("A Acaideria!");
  display.display(); 
  tres();  //delay 3s
  tres();  //delay 3s
  tres();  //delay 3s
  // no total, delay de 9 segundos
  display.stopscroll();

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  wifiConnect();
  Serial.println("WiFi connected");
  client.setServer(mqttServer, port);
  client.setCallback(callback);
} 

//wifi
void wifiConnect() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    um();
    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");
      tres();
    }
  }
}

//topico
void callback(char* topic, byte* mensagem, unsigned int length) {
  Serial.print("Mensagem recebida no topico: ");
  Serial.print(topic);
  
  for (int i = 0; i < length; i++) {
    Serial.print((char)mensagem[i]);
    stMessage += (char)mensagem[i];
  }
  Serial.println();

  if (String(topic) == "FelEJot/trab") {
    Serial.println(topic);
    if(stMessage == "verde"){
      botaoverde.isReleased(); }
    else if(stMessage == "vermelho"){
      botaovermelho.isReleased(); }
    else if(stMessage == "amarelo"){
      botaoamarelo.isReleased(); }
  }
} 

//void loop
void loop() {
  botaovermelho.loop();
  botaoamarelo.loop();
  botaoverde.loop();

  if (!client.connected()) {
    mqttReconnect();
  }
  client.loop();

  switch (estado) {
    case 0: tamanho_acai(); break;
    case 1: tipo_acai(); break;
    case 2: creme_acai (); break;
    case 3: fruta_acai (); break;
    case 4: extra_acai (); 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(botaovermelho.isReleased()) {
      tamanho = "770ml";
      analogWrite(led_vermelho, HIGH);
      um();
      analogWrite(led_vermelho, LOW);
      estado = 1;  }

    if(botaoamarelo.isReleased()) {
      tamanho = "550ml";
      analogWrite(led_amarelo, HIGH);
      um();
      analogWrite(led_amarelo, 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 - creme no acai
void creme_acai() { 
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 10);
  display.println("Creme do acai:");
  display.setCursor(10, 20);
  display.println("Ninho (verde)");
  display.setCursor(10, 30);
  display.println("Nutella (amarelo)");
  display.setCursor(10, 40);
  display.println("Oreo (vermelho)");
  display.display(); 

  if (botaoverde.isReleased()) {
    creme = "Ninho";
    analogWrite(led_verde, HIGH);
    um();
    analogWrite(led_verde, LOW);
    estado = 3; }

  if (botaoamarelo.isReleased()) {
    creme = "Nutella";
    analogWrite(led_amarelo, HIGH);
    um();
    analogWrite(led_amarelo, LOW);
    estado = 3; }

  if (botaovermelho.isReleased()) {
    creme = "Oreo";
    analogWrite(led_vermelho, HIGH);
    um();
    analogWrite(led_vermelho, LOW);
    estado = 3; }   
}

//pergunta 3 - frutas no acai
void fruta_acai() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 10);
  display.println("Fruta do acai:");
  display.setCursor(10, 20);
  display.println("Kiwi (verde)");
  display.setCursor(10, 30);
  display.println("Banana (amarelo)");
  display.setCursor(10, 40);
  display.println("Morango (vermelho)");
  display.display();  

  if (botaoverde.isReleased()) {
    fruta = "Kiwi";
    analogWrite(led_verde, HIGH);
    um();
    analogWrite(led_verde, LOW);
    estado = 4; }

  if (botaoamarelo.isReleased()) {
    fruta = "Banana";
    analogWrite(led_amarelo, HIGH);
    um();
    analogWrite(led_amarelo, LOW);
    estado = 4; }

  if (botaovermelho.isReleased()) {
    fruta = "Morango";
    analogWrite(led_vermelho, HIGH);
    um();
    analogWrite(led_vermelho, LOW);
    estado = 4; }   
}

//pergunta 4 - o que vai de mais no acai
void extra_acai() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 10);
  display.println("Extra do acai:");
  display.setCursor(10, 20);
  display.println("Ovomaltine (verde)");
  display.setCursor(10, 30);
  display.println("Kit Kat (amarelo)");
  display.setCursor(10, 40);
  display.println("Granola (vermelho)");
  display.display(); 

  if (botaoverde.isReleased()) {
    extra = "Ovomaltine";
    analogWrite(led_verde, HIGH);
    um();
    analogWrite(led_verde, LOW);
    estado = 5; }

  if (botaoamarelo.isReleased()) {
    extra = "Kit Kat";
    analogWrite(led_amarelo, HIGH);
    um();
    analogWrite(led_amarelo, LOW);
    estado = 5; }

  if (botaovermelho.isReleased()) {
    extra = "Granola";
    analogWrite(led_vermelho, HIGH);
    um();
    analogWrite(led_vermelho, LOW);
    estado = 5; }  
}

// valor da gorjeta - vem do case 5 pra cá
void rs_gorjeta() {
  display.clearDisplay();
  potencia = analogRead(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; }
}