// GxEPD_Example : with Wifi, HTTP request, and JSON filtering
// USE WITH GxGDEW042Z15 and BitmapLEK.h    
/*******************************************************************
    A sample project for making a HTTP GET request on an ESP8266
    and parsing and filtering it from JSON and display using a
    Waveshare ESP8266 e-paper driver and 4.2 (400x300) 3-color display

    2021 LEKtronics.com
 *******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ArduinoJson.h>

#include <GxEPD.h>
#include <GxGDEW042Z15/GxGDEW042Z15.h>    // 4.2" b/w/r
//#include GxEPD_BitmapExamples
#include "BitmapLEK.h"


// FreeFonts from Adafruit_GFX
//#include <Fonts/FreeMonoBold9pt7b.h>
//#include <Fonts/FreeMonoBold12pt7b.h>
//#include <Fonts/FreeMonoBold18pt7b.h>
//#include <Fonts/FreeMonoBold24pt7b.h>

#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>

// Waveshare e-Paper ESP8266 Driver Board
//GxIO_Class io(SPI,CS=15, DC=4, RST=5)
//GxEPD_Class display(io, RST=5, BUSY=12)
GxIO_Class io(SPI, 15, 4, 5); 
GxEPD_Class display(io, 5, 12); 

//------- Replace the following! ------
char ssid[] = "*************";       // your network SSID (name)
char password[] = "*********";  // your network key

// For HTTP requests
WiFiClient client;

// Just the base of the URL you want to connect to
#define TEST_HOST "api.weatherlink.com"

String freedom_temp_f;
//String freedom_wind_mph;
//String freedom_wind_dir;
//String freedom_windchill_f;
String freedom_observation_time;
int freedom_season;

const uint8_t* season_bitmap;
const uint8_t* temp_bitmap; 


int temp_f = 0;
int temp_rounded = 0;

//char Title[] = "---FREEDOM---";

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.println("setup");
  display.init(115200); // enable diagnostic output on Serial

    // Connect to the WiFI
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);

  // Attempt to connect to Wifi network:
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  IPAddress ip = WiFi.localIP();
  Serial.println(ip);
  Serial.println("setup done");
  freedom_season = 4;//a starting point
}

void loop()
{
  makeHTTPRequest();
  #define HAS_RED_COLOR
  //showBitmapExample();
  delay(960000);// 960000 is 15 minutes
}

void showBitmapExample()
{
  ////////////////////////display.drawPicture(BitmapLEK_winter_black, BitmapLEK_30_red, sizeof(BitmapLEK_winter_black), sizeof(BitmapLEK_30_red)); // black-butterfly red-flower
  //delay(5000);
  display.init(); 
  display.setRotation(0);
//  display.setFont(&FreeMonoBold9pt7b);
  //display.setTextColor(GxEPD_RED); 
  //display.drawPicture(epd_bitmap_thermometer_empty_grad_104x300 , epd_bitmap_120_104x300, sizeof(epd_bitmap_thermometer_empty_grad_104x300 ), sizeof(epd_bitmap_120_104x300));//black,red
  Serial.println(sizeof(BitmapWaveshare_black));
  Serial.println(sizeof(BitmapWaveshare_red));
  //  display.update();
  //display.hibernate();
  //delay(2000);
}
/////////////////////////////////

void makeHTTPRequest() {

  // Opening connection to server (Use 80 as port if HTTP)
  if (!client.connect(TEST_HOST, 80))
  {
    Serial.println(F("Connection failed"));
    return;
  }

  // give the esp a breather
  yield();

  // Send HTTP request
  client.print(F("GET "));
  // This is the second half of a request (everything that comes after the base URL)
  client.print("/v1/NoaaExt.json?user=001D0AE07E21&pass=hD43n2bOyq&apiToken=****************************"); 
  client.println(F(" HTTP/1.1"));

  //Headers
  client.print(F("Host: "));
  client.println(TEST_HOST);

  client.println(F("Cache-Control: no-cache"));

  if (client.println() == 0)
  {
    Serial.println(F("Failed to send request"));
    return;
  }
  //delay(100);
  // Check HTTP status
  char status[32] = {0};
  client.readBytesUntil('\r', status, sizeof(status));
  if (strcmp(status, "HTTP/1.1 200 OK") != 0)
  {
    Serial.print(F("Unexpected response: "));
    Serial.println(status);
    return;
  }

  // Skip HTTP headers
  char endOfHeaders[] = "\r\n\r\n";
  if (!client.find(endOfHeaders))
  {
    Serial.println(F("Invalid response"));
    return;
  }

  // This is probably not needed for most, but I had issues
  // with the Tindie api where sometimes there were random
  // characters coming back before the body of the response.
  // This will cause no harm to leave it in
  // peek() will look at the character, but not take it off the queue
  while (client.available() && client.peek() != '{')
  {
    char c = 0;
    client.readBytes(&c, 1);
    Serial.print(c);
    Serial.println("BAD");
  }

   // The huge input: an extract from Davis Weather response

const __FlashStringHelper* input_json = F(
  "{\"credit\": \"Davis Instruments Corp.\",\"credit_URL\": \"http://www.davisnet.com\","
  "\"disclaimer_url\": \"http://www.davisnet.com/about/terms.asp\",\"copyright_url\": \"http://www.davisnet.com/about/terms.asp\","
  "\"privacy_policy_url\": \"http://www.davisnet.com/about/privacy.asp\","
  "\"image\": {\"url\": \"http://www.weatherlink.com/images/Logo_Davis_reflxblu.jpg\",\"title\": \"Davis WeatherLink\", \"link\": \"http://www.weatherlink.com\"},"
  "\"suggested_pickup\": \"15 minutes after the hour\", \"suggested_pickup_period\": \"60\",\"dewpoint_c\": \"-0.6\","
  "\"dewpoint_f\": \"31.0\",\"dewpoint_string\": \"31.0 F (-0.6 C)\",\"heat_index_c\": \"2.2\",\"heat_index_f\": \"36.0\",\"heat_index_string\": \"36.0 F (2.2 C)\","
  "\"location\": \"Pemberville, OH, United States of America\",\"latitude\": \"41.40177\",\"longitude\": \"-83.44719\",\"observation_time\": \"Last Updated on Dec 13 2021, 9:29 pm EST\","
  "\"observation_time_rfc822\": \"Mon, 13 Dec 2021 21:29:31 -0500\",\"pressure_in\": \"30.362\",\"pressure_mb\": \"1028.2\",\"pressure_string\": \"1028.2 mb\","
  "\"relative_humidity\": \"80\",\"station_id\": \"larryk240\",\"temp_c\": \"2.4\",\"temp_f\": \"36.4\",\"temperature_string\": \"36.4 F (2.4 C)\","
  "\"wind_degrees\": \"225\",\"wind_dir\": \"Southwest\",\"wind_kt\": \"0.0\",\"wind_mph\": \"0.0\",\"windchill_c\": \"2.2\",\"windchill_f\": \"36.0\",\"windchill_string\": \"36.0 F (2.2 C)\","
  "\"davis_current_observation\": {\"DID\": \"001D0AE07E21\",\"station_name\": \"Freedom\",\"observation_age\": 12,\"dewpoint_day_high_f\": \"36\","
  "\"dewpoint_day_high_time\": \"4:15pm\",\"dewpoint_day_low_f\": \"26\",\"dewpoint_day_low_time\": \"7:20am\",\"dewpoint_month_high_f\": \"59\","
  "\"dewpoint_month_low_f\": \"14\",\"dewpoint_year_high_f\": \"82\",\"dewpoint_year_low_f\": \"-8\",\"heat_index_day_high_f\": \"49\",\"heat_index_day_high_time\": \"1:13pm\","
  "\"heat_index_month_high_f\": \"64\",\"heat_index_year_high_f\": \"109\",\"pressure_day_high_in\": \"30.362\",\"pressure_day_high_time\": \"9:23pm\","   
  "\"pressure_day_low_in\": \"30.228\",\"pressure_day_low_time\": \"12:11am\",\"pressure_month_high_in\": \"30.362\",\"pressure_month_low_in\": \"29.299\","   
  "\"pressure_tendency_string\": \"Rising Slowly\",\"pressure_year_high_in\": \"30.648\",\"pressure_year_low_in\": \"29.299\",\"rain_day_in\": \"0.0000\","   
  "\"rain_month_in\": \"1.1000\",\"rain_rate_day_high_in_per_hr\": \"0.0000\",\"rain_rate_hour_high_in_per_hr\": \"0.0000\",\"rain_rate_in_per_hr\": \"0.0000\","    
  "\"rain_rate_month_high_in_per_hr\": \"1.1100\",\"rain_rate_year_high_in_per_hr\": \"10.1100\",\"rain_storm_in\": \"0.0000\",\"rain_year_in\": \"40.6600\","
  "\"relative_humidity_day_high\": \"82\",\"relative_humidity_day_high_time\": \"8:09pm\",\"relative_humidity_day_low\": \"54\",\"relative_humidity_day_low_time\": \"12:24pm\","
  "\"relative_humidity_month_high\": \"97\",\"relative_humidity_month_low\": \"49\",\"relative_humidity_year_high\": \"98\",\"relative_humidity_year_low\": \"19\","
  "\"relative_humidity_in\": \"46\",\"relative_humidity_in_day_high\": \"47\",\"relative_humidity_in_day_high_time\": \"5:54pm\",\"relative_humidity_in_day_low\": \"45\","
  "\"relative_humidity_in_day_low_time\": \"10:01am\",\"relative_humidity_in_month_high\": \"48\",\"relative_humidity_in_month_low\": \"44\",\"relative_humidity_in_year_high\": \"56\","
  "\"relative_humidity_in_year_low\": \"31\",\"sunrise\": \"7:52am\",\"sunset\": \"5:05pm\",\"temp_day_high_f\": \"49.8\",\"temp_day_high_time\": \"2:48pm\","
  "\"temp_day_low_f\": \"31.2\",\"temp_day_low_time\": \"7:44am\",\"temp_month_high_f\": \"63.5\",\"temp_month_low_f\": \"19.7\",\"temp_year_high_f\": \"94.9\","
  "\"temp_year_low_f\": \"-4.1\",\"temp_in_day_high_f\": \"52.9\",\"temp_in_day_high_time\": \"7:26pm\",\"temp_in_day_low_f\": \"50.6\",\"temp_in_day_low_time\": \"9:35am\","
  "\"temp_in_f\": \"52.8\",\"temp_in_month_high_f\": \"58.5\",\"temp_in_month_low_f\": \"49.7\",\"temp_in_year_high_f\": \"90.8\",\"temp_in_year_low_f\": \"48.6\","
  "\"wind_day_high_mph\": \"19.0\",\"wind_day_high_time\": \"12:27pm\",\"wind_month_high_mph\": \"43.0\",\"wind_ten_min_avg_mph\": \"1.0\",\"wind_ten_min_gust_mph\": \"3.0\","
  "\"wind_year_high_mph\": \"43.0\",\"windchill_day_low_f\": \"28\",\"windchill_day_low_time\": \"4:10am\",\"windchill_month_low_f\": \"15\",\"windchill_year_low_f\": \"-6\""
  "},\"time_to_generate\": \"0.007791 seconds\"}");

  // The filter: it contains "true" for each value we want to keep

  DynamicJsonDocument filter (6144);
  filter["observation_time"] = true;
  filter["temp_f"] = true;
  //filter["wind_dir"] = true;
  //filter["wind_mph"] = true;
  //filter["windchill_f"] = true;
  

  // Deserialize the document
  DynamicJsonDocument doc (6144);
  
  deserializeJson(doc, input_json, DeserializationOption::Filter(filter));

  DeserializationError error = deserializeJson(doc, client);

    if (!error) {

  // Print the result
  //serializeJsonPretty(doc, Serial);

String freedom_observation_time = doc["observation_time"];
String freedom_temp_f = doc["temp_f"];
//String freedom_wind_mph = doc["wind_mph"];
//String freedom_wind_dir = doc["wind_dir"];
//String freedom_windchill_f = doc["windchill_f"];

///////////////////////////////////////////////////////////////////////////////////
// extract day and time from observation time
int delimiter, delimiter_1, delimiter_2, delimiter_3, delimiter_4, delimiter_5;
delimiter = freedom_observation_time.indexOf(" ");
delimiter_1 = freedom_observation_time.indexOf(" ", delimiter + 1);
delimiter_2 = freedom_observation_time.indexOf(" ", delimiter_1 +1);
delimiter_3 = freedom_observation_time.indexOf(" ", delimiter_2 +1);
delimiter_4 = freedom_observation_time.indexOf(" ", delimiter_3 +1);
delimiter_5 = freedom_observation_time.indexOf(" ", delimiter_4 +1);

String freedom_ob_day = freedom_observation_time.substring(delimiter_2 + 1, delimiter_4); //substring(beginning, end)

 if (freedom_ob_day == "Mar 21" ) {
    Serial.print("Season is ");
    Serial.println("Spring");
    int freedom_season = 1;  
}

  if (freedom_ob_day == "Jun 21" ) {
    Serial.print("Season is ");
    Serial.println("Summer");
    int freedom_season = 2;  
}

 if (freedom_ob_day == "Sep 21" ) {
    Serial.print("Season is ");
    Serial.println("Fall");
    int freedom_season = 3;  
}

if (freedom_ob_day == "Dec 21" ) {
    Serial.print("Season is ");
    Serial.println("Winter");
    int freedom_season = 4;
}

////////////////////////////////////////////////////////////////////////////////////


Serial.println("");
Serial.print("freedom_temp_f: ");
Serial.println(freedom_temp_f);
Serial.print("freedom_ob_day: ");
Serial.println(freedom_ob_day);

//Serial.print("freedom_wind_mph: ");
//Serial.println(freedom_wind_mph);
//Serial.print("freedom_wind_dir: ");
//Serial.println(freedom_wind_dir);
//Serial.print("freedom_windchill_f: ");
//Serial.println(freedom_windchill_f);

temp_f = freedom_temp_f.toInt(); //convert freedom_temp_f to an integer
//temp_f = -11;// troubleshooting

Serial.print("temp_f: ");
Serial.println(temp_f);

temp_rounded = (temp_f / 5);//divide temp_f by 5
Serial.print("temp_rounded: ");
Serial.println(temp_rounded);

  Serial.println(sizeof(BitmapLEK_winter_black));//BitmapLEK_spring_black // BitmapLEK_summer_black // BitmapLEK_fall_black // BitmapLEK_winter_black
  Serial.println(sizeof(BitmapLEK_25_red));//BitmapLEK_10neg_red to BitmapLEK_120_red

switch (freedom_season){
        case 1:
        season_bitmap = BitmapLEK_spring_black;
        break;
        case 2:
        season_bitmap = BitmapLEK_summer_black;
        break;
        case 3:
        season_bitmap = BitmapLEK_fall_black;
        break;
        case 4:
        season_bitmap = BitmapLEK_winter_black;
        break;
    }
    
switch (temp_rounded){
  case -2:
    Serial.println("display -10 degrees");
    temp_bitmap = BitmapLEK_10neg_red;
    break;
  case -1:
    Serial.println("display -5 degrees");
    temp_bitmap = BitmapLEK_5neg_red;
    break;
  case 0:
    Serial.println("display 0 degrees");
    temp_bitmap = BitmapLEK_0_red;
    break;
  case 1:
    Serial.println("display 5 degrees");
    temp_bitmap = BitmapLEK_5_red;
    break;
  case 2:
    Serial.println("display 10 degrees");
    temp_bitmap = BitmapLEK_10_red;
    break;
  case 3:
    Serial.println("display 15 degrees");
    temp_bitmap = BitmapLEK_15_red;
    break;
  case 4:
    Serial.println("display 20 degrees");
    temp_bitmap = BitmapLEK_20_red;
    break;
  case 5:
    Serial.println("display 25 degrees");
    temp_bitmap = BitmapLEK_25_red;
    break;
  case 6:
    Serial.println("display 30 degrees");
    temp_bitmap = BitmapLEK_30_red;
    break;
  case 7:
    Serial.println("display 35 degrees");
    temp_bitmap = BitmapLEK_35_red;
    break;
  case 8:
    Serial.println("display 40 degrees");
    temp_bitmap = BitmapLEK_40_red;
    break;
  case 9:
    Serial.println("display 45 degrees");
    temp_bitmap = BitmapLEK_45_red;
    break;
  case 10:
    Serial.println("display 50 degrees");
    temp_bitmap = BitmapLEK_50_red;
    break;
  case 11:
    Serial.println("display 55 degrees");
    temp_bitmap = BitmapLEK_55_red;
    break;
  case 12:
    Serial.println("display 60 degrees");
    temp_bitmap = BitmapLEK_60_red;
    break;
  case 13:
    Serial.println("display 65 degrees");
    temp_bitmap = BitmapLEK_65_red;
    break;
  case 14:
    Serial.println("display 70 degrees");
    temp_bitmap = BitmapLEK_70_red;
    break;
  case 15:
    Serial.println("display 75 degrees");
    temp_bitmap = BitmapLEK_75_red;
    break;
  case 16:
    Serial.println("display 80 degrees");
    temp_bitmap = BitmapLEK_80_red;
    break;
   case 17:
    Serial.println("display 85 degrees");
    temp_bitmap = BitmapLEK_85_red;
    break;
  case 18:
    Serial.println("display 90 degrees");
    temp_bitmap = BitmapLEK_90_red;
    break;
  case 19:
    Serial.println("display 95 degrees");
    temp_bitmap = BitmapLEK_95_red;
    break;
  case 20:
    Serial.println("display 100 degrees");
    temp_bitmap = BitmapLEK_100_red;
    break;
  case 21:
    Serial.println("display 105 degrees");
    temp_bitmap = BitmapLEK_105_red;
    break;
  case 22:
    Serial.println("display 110 degrees");
    temp_bitmap = BitmapLEK_110_red;
    break;
  case 23:
    Serial.println("display 115 degrees");
    temp_bitmap = BitmapLEK_115_red;
    break;
  case 24:
    Serial.println("display 120 degrees");
    temp_bitmap = BitmapLEK_120_red;
    break;
}

display.drawPicture(season_bitmap, temp_bitmap, 15000, 15000);

  } else {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }
}
