#define BLYNK_PRINT Serial
#define BLYNK_TEMPLATE_ID "TMPL6cvdTf27v"
#define BLYNK_TEMPLATE_NAME "Hit Listrik"
#define BLYNK_AUTH_TOKEN "KBgWHCtI5ljE1Ti0A3KtHwqvGwYIkwgI"

#include <BlynkSimpleEsp32.h>

char auth[] =  BLYNK_AUTH_TOKEN; 
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
#define ledGreen 13 //define2 ni buat inisialisai pin alat aja
#define ledRed 12
#define s1 2 //switch
#define s2 4
#define s3 15
#define buzzer 5
#define VIRTUAL_PIN_6 V6 //inisialisasi Pin VP Blynk
#define VIRTUAL_PIN_7 V7
#define VIRTUAL_PIN_8 V8
const String green = "GREEN"; //buat inisialisasi aja, buat hemat line code
const String red = "RED";
const String buz = "BUZZER";
int counter1 = 0; //ini buat nampung nilai cukk
int counter2 = 0;
int counter3 = 0;
const float wattPrice = 1.2; 
const float led1_Watt = 2;
const float led2_Watt = 4;
const float buzz_Watt = 6;  
int long t1 = 0;
int tokenListrik = 100;
int statusLED1 = LOW;  //saat start, mengasumsikan bahwa led1 ini masih on dlu
int statusLED2 = LOW;
int statusLED3 = LOW;
int statusBUZZ = LOW;

void myTone(int pin) // buzzer bunyi ini
{
  ledcAttachPin(pin, 0);             // pin, channel
  ledcWriteNote(0, NOTE_F, 4);    // channel, frequency, octavnya
}

void myNoTone(int pin)
{
  ledcDetachPin(pin); // buzzer enggak bunyi
}

void konversiWaktu(int angka1, float watt, int pin){  //fungsi buat konversi dari mili, detik, dan jam
  int long angka2 = millis();
  Serial.print("Waktu OFF : ");
  Serial.println(angka2);
  Serial.print("Total WaktuON/Watt/Price : ");
  int totalDetik = (angka2 - angka1)/1000;
  double wattHour = totalDetik * double(watt);
  double price = wattHour * double(wattPrice);
  String d = String(totalDetik);
  d.concat(" Detik");
  String w = String(wattHour);
  w.concat(" Watt");
  String p = String(price);
  p.concat(" Rupiah");
  String total = d + "/" + w  + "/" + p;
  Serial.println(total);
  Blynk.virtualWrite(pin, total); 
}

void counterAndTon(int counter, int Ton, String type){  //fungsi Ton nya, counter, sama type(LED/BUZZER)
  Serial.print("\nLED " + String(type) + " : ");
  Serial.println(counter);
  Serial.print("Waktu On : ");
  Serial.println(Ton);
}

void controller(){ //fungsi penting 
  int switch1 = digitalRead(s1);
  int switch2 = digitalRead(s2);
  int switch3 = digitalRead(s3);

  //Configurasi Buat LED GREEN
  if(switch1 == HIGH){
    digitalWrite(ledGreen, HIGH);
    Blynk.virtualWrite(V0, HIGH);
    if(statusLED1 == LOW){
     counter1 += 1;   
     t1 = millis();
     Blynk.virtualWrite(V3, counter1);
     counterAndTon(counter1, t1, green);
     statusLED1 = HIGH;
   } 
  }else{
    digitalWrite(ledGreen, LOW);
    Blynk.virtualWrite(V0, LOW);
    if(statusLED1 == HIGH ){
      konversiWaktu(t1, led1_Watt, VIRTUAL_PIN_6);
      statusLED1 = LOW;
    }
  }

  //Configurasi buat LED RED
  if(switch2 == HIGH){
    digitalWrite(ledRed, HIGH);
    Blynk.virtualWrite(V1, HIGH);
    if(statusLED2 == LOW){ //kita ubah status dari led mati jadi hidup
     counter2 += 1;   
     t1 = millis();
     Blynk.virtualWrite(V4, counter2);
     counterAndTon(counter2, t1, red);
     statusLED2 = HIGH;
   } 
  }else{
    digitalWrite(ledRed, LOW);
    Blynk.virtualWrite(V1, LOW);
    if(statusLED2 == HIGH ){ //kita mengembalikan status awal dari lednya (mati)
      konversiWaktu(t1, led2_Watt, VIRTUAL_PIN_7);
      statusLED2 = LOW;
    }
  }

  //Configurasi buat Buzzer
  if(switch3 == HIGH){
    myTone(buzzer);
    Blynk.virtualWrite(V2, HIGH);
    if(statusBUZZ == LOW){
     counter3 += 1;   
     t1 = millis();
     Blynk.virtualWrite(V5, counter3);
     counterAndTon(counter3, t1, buz);
     statusBUZZ = HIGH;
   } 
  }else{
    myNoTone(buzzer);
    Blynk.virtualWrite(V2, LOW);
    if(statusBUZZ == HIGH ){
      konversiWaktu(t1, buzz_Watt, VIRTUAL_PIN_8);
      statusBUZZ = LOW;
    }
  }

}

void setup() {
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass);
  pinMode(ledGreen, OUTPUT);
  pinMode(ledRed, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(s1, INPUT_PULLUP);
  pinMode(s2, INPUT_PULLUP);
  pinMode(s3, INPUT_PULLUP);
}

void loop() {
  Blynk.run();
  controller(); //manggil fungsi controller biar program jalan brooo
  delay(500);
}