/*
   Inkplate2_Hourly_Weather_Station example for Soldered Inkplate 2
   For this example you will need only USB cable, Inkplate 2 and a WiFi with stable Internet connection.
   Select "Soldered Inkplate2" from Tools -> Board menu.
   Don't have "Soldered Inkplate2" option? Follow our tutorial and add it:
   https://soldered.com/learn/add-inkplate-6-board-definition-to-arduino-ide/
   
   This example will show you how you can use Inkplate 2 to display API data,
   e.g. OpenWeatherMap API, and weatherstack for real time data
   
   IMPORTANT:
   Make sure to change your desired city, timezone and wifi credentials below
   Also have ArduinoJSON installed in your Arduino libraries
   
   Want to learn more about Inkplate? Visit www.inkplate.io
   Looking to get support? Write on our forums: https://forum.soldered.com/
   5 April 2022 by e-radionica.com

   In order to convert your images into a format compatible with Inkplate
   use the Soldered Image Converter available at:
   https://github.com/SolderedElectronics/Soldered-Image-Converter/releases
*/

// Next 3 lines are a precaution, you can ignore those, and the example would also work without them
#ifndef ARDUINO_INKPLATE2
#error "Wrong board selection for this example, please select Soldered Inkplate 2 in the boards menu."
#endif

#include "Inkplate.h" // Include Inkplate library to the sketch

#include "Network.h" // Header file for easier code readability

// Including fonts used
#include "Fonts/SourceSansPro_Regular8pt7b.h"

// Including icons generated by the py file
#include "icons.h"

// Delay between API calls, about 1000000 per month, which is the free tier limit
#define DELAY_MS 267800L
#define DELAY_WIFI_RETRY_SECONDS 10

// Inkplate object
Inkplate display;

// All our network functions are in this object, see Network.h
Network network;

// Change to your wifi ssid and password
char ssid[] = "";
char pass[] = "";

// Change to your api key, if you don't have one, head over to:
// https://openweathermap.org/guide , register and copy the key provided
char apiKey[] = "";

// Coordinates of your city sent to the api
char lon[] = "18.5947808";
char lat[] = "45.5510548";

// Uncomment this for MPH and Fahrenheit output, also uncomment it in the begining of Network.cpp
// #define AMERICAN

// Contants used for drawing icons
char abbrs[32][32] = {"01d", "02d", "03d", "04d", "09d", "10d", "11d", "13d", "50d",
                      "01n", "02n", "03n", "04n", "09n", "10n", "11n", "13n", "50n"};

const uint8_t *s_logos[18] = {
    icon_s_01d, icon_s_02d, icon_s_03d, icon_s_04d, icon_s_09d, icon_s_10d, icon_s_11d, icon_s_13d, icon_s_50d,
    icon_s_01n, icon_s_02n, icon_s_03n, icon_s_04n, icon_s_09n, icon_s_10n, icon_s_11n, icon_s_13n, icon_s_50n,
};

// Variables for storing temperature
char temps[3][8] = {
    "-",
    "-",
    "-",
};

// Variables for storing hour strings
char hours[3][8] = {
    "",
    "",
    "",
};

char currentTime[16] = "--:--";

char abbr1[16];
char abbr2[16];
char abbr3[16];

// function defined below
void drawTemps();

void setup()
{
    // Begin serial and display
    Serial.begin(115200);
    display.begin();

    // Initial cleaning of buffer and physical screen
    display.clearDisplay();

    // Connect Inkplate to the WiFi network
    // Try connecting to a WiFi network.
    // Parameters are network SSID, password, timeout in seconds and whether to print to serial.
    // If the Inkplate isn't able to connect to a network stop further code execution and print an error message.
    if (!display.connectWiFi(ssid, pass, WIFI_TIMEOUT, true))
    {
        //Can't connect to netowrk
        // Clear display for the error message
        display.clearDisplay();
        // Set the font size;
        display.setTextSize(1);
        // Set the cursor positions and print the text.
        display.setCursor(0, 0);
        display.print(F("Unable to connect to "));
        display.println(F(ssid));
        display.println(F("Please check SSID and PASS!"));
        // Display the error message on the Inkplate and go to deep sleep
        display.display();
        esp_sleep_enable_timer_wakeup(1000L * DELAY_WIFI_RETRY_SECONDS);
        (void)esp_deep_sleep_start();
    }

    // After connecting to WiFi we need to get internet time from NTP server
    time_t nowSec;
    struct tm timeInfo;
    // Fetch current time in epoch format and store it
    display.getNTPEpoch(&nowSec);
    gmtime_r(&nowSec, &timeInfo);
    Serial.print(F("Current time: "));
    Serial.print(asctime(&timeInfo));

    // Clear display
    display.clearDisplay();

    // Get all relevant data, see Network.cpp for info
    while (!network.getData(lon, lat, apiKey, temps[0], temps[1], temps[2], abbr1, abbr2, abbr3))
    {
        Serial.println("Retrying fetching data!");
        delay(5000);
    }
    network.getTime(currentTime);
    network.getHours(hours[0], hours[1], hours[2]);

    // Draw data, see functions below for info
    drawTemps();

    // Refresh full screen every fullRefresh times, defined above
    display.display();

    // Go to sleep before checking again
    // rtc_gpio_isolate(GPIO_NUM_12);   // Isolate/disable GPIO12 on ESP32 (only to reduce power consumption in sleep)
    esp_sleep_enable_timer_wakeup(1000L * DELAY_MS); // Activate wake-up timer
     
    esp_deep_sleep_start();       // Put ESP32 into deep sleep. Program stops here
}

void loop()
{
    // Never here! If you are using deep sleep, the whole program should be in setup() because the board restarts each
    // time. loop() must be empty!
}

// Function for drawing temperatures
void drawTemps()
{
    // Drawing 4 black rectangles in which temperatures will be written

    display.drawRect(5, 5, 60, 94, INKPLATE2_BLACK); // Draw some rectangles
    display.drawRect(75, 5, 60, 94, INKPLATE2_BLACK);
    display.drawRect(145, 5, 60, 94, INKPLATE2_BLACK);

    display.setFont(&SourceSansPro_Regular8pt7b);         // Set custom font
    display.setTextSize(1);                               // Set font size
    display.setTextColor(INKPLATE2_RED, INKPLATE2_BLACK); // Set font color and background color

    display.setCursor(
        18,
        20); // Set cursor, custom font uses different method for setting cursor
             // You can find more about that here https://learn.adafruit.com/adafruit-gfx-graphics-library/using-fonts
    display.println("Now");

    display.setCursor(92, 20);
    display.println(hours[1]);

    display.setCursor(162, 20);
    display.println(hours[2]);

    // Drawing temperature values into black rectangles
    display.setTextColor(INKPLATE2_BLACK, INKPLATE2_WHITE);

    display.setCursor(20, 40);
    display.print(temps[0]);
    display.println(F("C"));

    display.setCursor(90, 40);
    display.print(temps[1]);
    display.println(F("C"));

    display.setCursor(160, 40);
    display.print(temps[2]);
    display.println(F("C"));

    for (int i = 0; i < 18; ++i)
    {
        // If found draw specified icon
        if (strcmp(abbr1, abbrs[i]) == 0)
            display.drawBitmap(11, 48, s_logos[i], 48, 48, INKPLATE2_BLACK, INKPLATE2_WHITE);
    }

    for (int i = 0; i < 18; ++i)
    {
        // If found draw specified icon
        if (strcmp(abbr2, abbrs[i]) == 0)
            display.drawBitmap(81, 48, s_logos[i], 48, 48, INKPLATE2_BLACK, INKPLATE2_WHITE);
    }

    for (int i = 0; i < 18; ++i)
    {
        // If found draw specified icon
        if (strcmp(abbr3, abbrs[i]) == 0)
            display.drawBitmap(151, 48, s_logos[i], 48, 48, INKPLATE2_BLACK, INKPLATE2_WHITE);
    }
}
