/* Fill-in information from Blynk Device Info here */
#define BLYNK_TEMPLATE_ID           "<FILL HERE YOUR BLYNK TEMPLATE ID"
#define BLYNK_TEMPLATE_NAME         "FILL HERE YOUR BLYNK TEMPLATE NAME"
#define BLYNK_AUTH_TOKEN            "FILL HERE YOUR BLYNK AUTHENTICATION TOKEN"

// Your WiFi credentials.
char ssid[] = "FILL HERE THE NAME OF YOUR WIFI NETWORK";
char pass[] = "FILL HERE THE PASSWORD OF YOUR WIFI NETWORK";

//Defines for your TV
#define MY_TV_PROTOCOL <FILL HERE YOUR TV PROTOCOL>
#define MY_SIGNAL_BITS_COUNT <FILL HERE YOUR SIGNAL BIT COUNT>
#define POWER_ON_SIGNAL <FILL HERE YOUR POWER-ON SIGNAL>

#define BLYNK_PRINT SerialUSB

#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <Adafruit_CircuitPlayground.h>
#include "NokiaRingtone.h"

#define EspSerial Serial1
#define ESP8266_BAUD 115200

#define NEEDED_AMOUNT_OF_SONGS 3
#define NEOPIXELS_COLOR 0x00FF00 // Green
#define NOISE_UPDATE_INTERVAL_MS 1000
#define NEOPIXELS_UPDATE_INTERVAL_MS 1000
#define SOUND_PRESSURE_LEVEL_SAMPLE_DURATION_MS 50
#define LOUD_NOISE_THRESHOLD 75
#define LOUD_NOISE_DETECTION_MEESAGE 1
#define PHYSICAL_BUTTON_PRESSED_MESSAGE 0

ESP8266 wifi(&EspSerial);

long lastNoiseUpdateDeliverTime = 0;
long lastNeopixelsColorSetTime = 0;
bool wasLoudNoiseMeasured = false;
bool isMailReceived = false;
bool areNeopixelsOn = false;
bool shouldNotifyUponNewSong = false;
long numberOfSongsReceived = 0;

void setup()
{
  CircuitPlayground.begin();
  SerialUSB.begin(9600);
  EspSerial.begin(ESP8266_BAUD);
  delay(10);

  Blynk.begin(BLYNK_AUTH_TOKEN, wifi, ssid, pass);
  Serial.println("Connected to Blynk");
}

void loop()
{
    Blynk.run();

    if (shouldDetectNoise()) {
        const float soundPressureLevelDecibles = CircuitPlayground.mic.soundPressureLevel(
            SOUND_PRESSURE_LEVEL_SAMPLE_DURATION_MS);
        Serial.print("Sound pressure (dB): ");
        Serial.println(soundPressureLevelDecibles);
        
        if (soundPressureLevelDecibles >= LOUD_NOISE_THRESHOLD) {
          wasLoudNoiseMeasured = true;
          Serial.println("Notifying blynk that loud noise detected");
          // Notify blynk about loud noise and let the fun begin
          Blynk.virtualWrite(V0, LOUD_NOISE_DETECTION_MEESAGE);
        }
        
        lastNoiseUpdateDeliverTime = millis();
    }

    if (shouldSetNeopixelsColor()) {
        // Switch Neopixels state (on->off, off->on)
        setNeopixels(!areNeopixelsOn);

        areNeopixelsOn = !areNeopixelsOn;
        lastNeopixelsColorSetTime = millis();
    }

    const bool leftButtonPressed = CircuitPlayground.leftButton();
    const bool rightButtonPressed = CircuitPlayground.rightButton();
    if (isMailReceived && (leftButtonPressed || rightButtonPressed)) {
      // Upon button press, wait for new songs to arrive
      isMailReceived = false;
      shouldNotifyUponNewSong = true;
      setNeopixels(false);
      
      // Notify blynk that user pressed on one of the physical buttons after received a mail
      Blynk.virtualWrite(V0, PHYSICAL_BUTTON_PRESSED_MESSAGE);
      Serial.println("Physical button pressed, moving to Telegram flow");
    }
}

bool shouldDetectNoise() {
  return !wasLoudNoiseMeasured && ((millis() - lastNoiseUpdateDeliverTime) > NOISE_UPDATE_INTERVAL_MS);
}

bool shouldSetNeopixelsColor() {
  return isMailReceived && ((millis() - lastNeopixelsColorSetTime) > NEOPIXELS_UPDATE_INTERVAL_MS);
}


void setNeopixels(bool shouldTurnOn) {
   for (int i = 0; i < 10; ++i) {
     CircuitPlayground.setPixelColor(i, shouldTurnOn ? NEOPIXELS_COLOR: 0);
   }
}
// eMail received notification sent from Blynk
BLYNK_WRITE(V1) {
    Serial.println("eMail received! Watch your inbox");
    isMailReceived = true;
}

// A new song was added to your spotify playlist
BLYNK_WRITE(V2) {
    if (shouldNotifyUponNewSong) {
      Serial.println("A new song was added to your spotify playlist!");
      numberOfSongsReceived++;
      CircuitPlayground.playTone(500, 100, false);
    }
    
    if (numberOfSongsReceived == NEEDED_AMOUNT_OF_SONGS) {
      // Reached expected number of songs sent by friends! Turn on TV and play a nice melody!
      CircuitPlayground.irSend.send(MY_TV_PROTOCOL, POWER_ON_SIGNAL, MY_SIGNAL_BITS_COUNT);
      PlayNokiaRingtone();
      numberOfSongsReceived = 0;
      // Start listening again for loud noise
      wasLoudNoiseMeasured = false;
      shouldNotifyUponNewSong = false;
    }
}
