#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32// OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

#include <Adafruit_NeoPixel.h>
#define PIN_NEO_PIXEL 2  // Arduino pin that connects to NeoPixel
#define NUM_PIXELS 1    // The number of LEDs (pixels) on NeoPixel
#define DELAY_INTERVAL 250  // 250ms pause between each pixel

#include <DHT.h>
#define DHTPIN 3    // Digital pin connected to the DHT sensor 
#define DHTTYPE    DHT22     // DHT 22 (AM2302)

#include <Tone.h>

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_BMP085 bmp;
Adafruit_NeoPixel NeoPixel(NUM_PIXELS, PIN_NEO_PIXEL, NEO_GRB + NEO_KHZ800);
DHT dht(DHTPIN, DHTTYPE);
Tone buzzer;

int idx = 0;

void setup() {

  // BMP180 Initialization
  Serial.begin(9600);
  if (!bmp.begin()) {
	Serial.println("Could not find a valid BMP085 sensor, check wiring!");
	while (1) {}
  }

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 initialization failed"));
    while(true);
  }

  //Neopixel initialization
  NeoPixel.begin();

  //DHT initialization
  dht.begin();

  //Buzzer Initialization
  buzzer.begin(4);


  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  buzzer.play(262);
  delay(273);
  buzzer.play(330);
  delay(273);
  buzzer.play(392);
  delay(273);
  buzzer.play(523);
  delay(818);
  buzzer.stop();
  // delay(500); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(10, 10, SSD1306_WHITE);

  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
}
  
void loop() {
  NeoPixel.clear();
  NeoPixel.setPixelColor(0, NeoPixel.Color(0, 255, 0));  // it only takes effect if pixels.show() is called
  NeoPixel.show();                                           // send the updated pixel colors to the NeoPixel hardware.

  // Pre-processing sensor datas
  float bmpTemp = bmp.readTemperature();
  float bmpPressure = bmp.readPressure()/100.0;
  float dhtTemp = dht.readTemperature();
  float dhtHumidity = dht.readHumidity();
  float avgTemp = (bmpTemp+dhtTemp)/2.0;
  float sgpTVOC = analogRead(A1);
  float sgpCO2eq = analogRead(A2);
  // float sgpTVOC = 0;
  // float sgpCO2eq = 0;
  unsigned long timeElapsed = millis()/1000;
  // float seriesData[7] = {timeElapsed, bmpTemp, dhtTemp, bmpPressure, dhtHumidity, sgpTVOC, sgpCO2eq};
  // for(int i = 0; i < sizeof(seriesData); i++){
  //   Serial.print(seriesData[i], ", ");
  // }
  // Serial.println("");
  // // Serial.println(seriesData);

  // Check if any reads failed and exit early (to try again).
  if (isnan(dhtTemp) || isnan(dhtHumidity)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }


  // Display main display
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  // display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 0);
  display.print(timeElapsed, "S");
  // display.print("Sensing...");
  printBattery();

  // Display important sensing value
  display.setCursor(0, 8);
  printTVOC(sgpTVOC);

  // Display additional sensing values
  if( idx == 0 ){
    display.setCursor(0, 16);
    printCO2eq(sgpCO2eq);
    display.setCursor(0, 24);
    printPressure(bmpPressure);
  }
  if( idx == 1){
    display.setCursor(0, 16);
    printTemp(avgTemp);
    display.setCursor(0, 24);
    printHumidity(dhtHumidity);
  }

  display.display();
  
  idx++;
  if( idx == 2 ){ idx = 0; }
  delay(1000);
}

void printBattery(){
  display.setTextColor(WHITE, BLACK);
  int sensorValue = analogRead(A0); //read the A0 pin value
  float voltage = sensorValue * (5.00 / 1023.00);
  // float voltage = sensorValue * (5.00 / 1023.00) * 2; //convert the value to a true voltage. USE THIS WHEN V_IN IS 9V AND USING VOLTAGE DIVIDER!
  display.setCursor(90,0);
  display.print(voltage); //print the voltage to LCD
  display.println(" V");

  //full charged alert
  if (voltage > 4.15){
    display.setCursor(0, 0);
    display.print("FULLY CHARGED");
  }

  //low battery alert
  if (voltage < 3.50){
    display.setCursor(0, 0);
    display.print("LOW BATTERY");
  }
}

void printPressure(float sensorValue){
  display.print("Pressure: ");
  display.print(sensorValue);
  display.print(" hPa");
}

void printTVOC(float sensorValue){
  // display.println("TVOC:             ppb");
  display.print("TVOC: ");
  display.print(sensorValue);
  display.print(" ppb");
}

void printCO2eq(float sensorValue){
  // display.println("CO2eq:            ppm");
  display.print("CO2eq: ");
  display.print(sensorValue);
  display.print(" ppm");
}

void printTemp(int sensorValue){
  display.print("Temp:         ");
  display.print(sensorValue);
  // display.print(char(248), "C");
  // display.print((char)248, "C");
  display.print(" `C");
  // display.print((char)247, "C");
}

void printHumidity(int sensorValue){
  display.print("Humidity:       ");
  display.print(sensorValue);
  display.print(" %");
}
nano:12
nano:11
nano:10
nano:9
nano:8
nano:7
nano:6
nano:5
nano:4
nano:3
nano:2
nano:GND.2
nano:RESET.2
nano:0
nano:1
nano:13
nano:3.3V
nano:AREF
nano:A0
nano:A1
nano:A2
nano:A3
nano:A4
nano:A5
nano:A6
nano:A7
nano:5V
nano:RESET
nano:GND.1
nano:VIN
nano:12.2
nano:5V.2
nano:13.2
nano:11.2
nano:RESET.3
nano:GND.3
BMP180Breakout
chip1:VCC
chip1:GND
chip1:SCL
chip1:SDA
oled1:GND
oled1:VCC
oled1:SCL
oled1:SDA
pot1:GND
pot1:SIG
pot1:VCC
rgb1:VDD
rgb1:DOUT
rgb1:VSS
rgb1:DIN
dht1:VCC
dht1:SDA
dht1:NC
dht1:GND
bz1:1
bz1:2
r1:1
r1:2
pot2:GND
pot2:SIG
pot2:VCC
pot3:GND
pot3:SIG
pot3:VCC