#include <Wire.h>
// Instructables Internet of Things Class sample code
// Circuit Displays Internet Data
// Weather data is collected in a feed
// Multiple NeoPixels visualize the weather condition
//
// Modified by Becky Stern 2017
// based on the Adafruit IO Subscription Example

// Adafruit invests time and resources providing this open source code.
// Please support Adafruit and open source hardware by purchasing
// products from Adafruit!
//
// Written by Todd Treece for Adafruit Industries
// Copyright (c) 2016 Adafruit Industries
// Licensed under the MIT license.
//
// All text above must be included in any redistribution.

/************************ Adafruit IO Configuration *******************************/

// visit io.adafruit.com if you need to create an account,
// or if you need your Adafruit IO key.
#define IO_USERNAME    "imntlg"
#define IO_KEY         "aio_lmxW94CDmrvv2a3ArmL2VR5FX9EP"

/******************************* WIFI Configuration **************************************/

#define WIFI_SSID       "Internet Of Things Class"
#define WIFI_PASS       "iheartarduino"

#include "AdafruitIO_WiFi.h"
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);

/************************ Main Program Starts Here *******************************/
#include <ESP8266WiFi.h>
#include <AdafruitIO.h>
#include <Adafruit_MQTT.h>
#include <ArduinoHttpClient.h>
#include <Servo.h>

#include <Adafruit_NeoPixel.h>

#define PIXELS_PIN 15   //Pin connected to the NeoPixel data input
#define NUM_LEDS   9    // Number of NeoPixels
#define BRIGHTNESS 25
#define PIXEL_TYPE NEO_GRB + NEO_KHZ800   // Type of the NeoPixels (see strandtest example).
#define SERVO1_PIN 12  // Define the pin for servo1
#define SERVO2_PIN 13 // Define the pin for servo2

Servo servo1;  // create servo object to control servo on pin 9
Servo servo2;  // create servo object to control servo on pin 10

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIXELS_PIN, PIXEL_TYPE + NEO_KHZ800);

AdafruitIO_Feed *precipitation = io.feed("precipitation"); // set up the 'precipitation' feed

void setup() {
servo1.attach(12);
servo2.attach(13);
  strip.setBrightness(BRIGHTNESS);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  // start the serial connection
  Serial.begin(115200);

  // connect to io.adafruit.com
  Serial.print("Connecting to Adafruit IO");
  io.connect();
  
  // set up a message handler for the 'precipitation' feed.
  // the handleMessage function (defined below)
  // will be called whenever a message is
  // received from adafruit io.
  precipitation->onMessage(handleMessage);

  // wait for a connection
  while(io.status() < AIO_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  // we are connected
  Serial.println();
  Serial.println(io.statusText());

}

void loop() {

  // io.run(); is required for all sketches.
  // it should always be present at the top of your loop
  // function. it keeps the client connected to
  // io.adafruit.com, and processes any incoming data.
  io.run();

}

// this function is called whenever a message
// is received from Adafruit IO. it was attached to
// the feed in the setup() function above.
void handleMessage(AdafruitIO_Data *data) {
  
  lightPixels(strip.Color(0, 0, 0, 0)); // reset all pixels to off when new info is received

  String forecast = data->toString(); // store the incoming weather data in a string
  
  Serial.print("received <- ");
  Serial.println(forecast);
  
  //the following strings store the varous IFTTT weather report words I've discovered so far
  String rain = String("Rain");
  String lightrain = String("Light Rain");
  String rainshower = String ("Rain Shower");
  String AMshowers = String ("AM Showers");
  
  String rainandsnow = String("Rain and Snow");
  String snow = String("Snow");
  String snowshower = String("Snow Shower");
  
  String cloudy = String("Cloudy");
  String mostlycloudy = String("Mostly Cloudy");
  String partlycloudy = String("Partly Cloudy");
  
  String clearsky = String("Clear");
  String fair = String("Fair");
  String sunny = String("Sunny");

  // These if statements compare the incoming weather variable to the stored conditions, and control the NeoPixels accordingly.
  
  // if there's rain in the forecast
  if (forecast.equalsIgnoreCase(rain) || forecast.equalsIgnoreCase(lightrain) || forecast.equalsIgnoreCase(rainshower) || forecast.equalsIgnoreCase(AMshowers)){
    Serial.println("precipitation in the forecast today is rain");
    servo2.write(15);  // Rotate servo1 90 degrees clockwise
    delay(1000);
    servo1.write(15);   // Return servo2 to the initial position
    lightPixels(strip.Color(15, 42, 253));
  }
  
  // if there's snow in the forecast
  if (forecast.equalsIgnoreCase(snow) || forecast.equalsIgnoreCase(rainandsnow) || forecast.equalsIgnoreCase(snowshower)){
    Serial.println("precipitation in the forecast today is snow");
   servo2.write(15);  // Rotate servo1 90 degrees clockwise
    delay(1000);
    servo1.write(15);   // Return servo2 to the initial position
    lightPixels(strip.Color(255, 255, 255));
  }
  
  // if there's sun in the forecast
  if (forecast.equalsIgnoreCase(clearsky) || forecast.equalsIgnoreCase(fair) || forecast.equalsIgnoreCase(sunny)){
    Serial.println("some kind of sun in the forecast today");
    servo1.write(60);   // Return servo1 to the initial position
    delay(1000);
    servo2.write(60);  // Rotate servo2 90 degrees clockwise
    lightPixels(strip.Color(253, 187, 54));
  }
  // if there're clouds in the forecast
  if (forecast.equalsIgnoreCase(cloudy) || forecast.equalsIgnoreCase(mostlycloudy) || forecast.equalsIgnoreCase(partlycloudy)){
    Serial.println("cloudy sky in the forecast today");
    servo1.write(60); 
    delay(1000);
    servo2.write(15);   // Return servo2 to the initial position
    lightPixels(strip.Color(99, 135, 255));
   }
   strip.show(); // display the changes
  
}

// Function to set all the NeoPixels to the specified color.
void lightPixels(uint32_t color) {
  for (int i=0; i<NUM_LEDS; ++i) {
    strip.setPixelColor(i, color);
  }
  strip.show();
}
