#ifndef TG_INFLUX_H
#define TG_INFLUX_H

#define DEVICE "ESP32"
#include <Arduino.h>


#include <InfluxDbClient.h>

#include "../sensor/sensor.h"
#include "../owm/owm.h"

const char* cert = "-----BEGIN CERTIFICATE-----\n\
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n\
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n\
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n\
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n\
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n\
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n\
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n\
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n\
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n\
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n\
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n\
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n\
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n\
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n\
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n\
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n\
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n\
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n\
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n\
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n\
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n\
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n\
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n\
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n\
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n\
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n\
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n\
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n\
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n\
-----END CERTIFICATE-----\n\
";


class Influx {

public:
    Influx(Sensor* _sensor, OWM* _owm[]): sensor(_sensor), owm(_owm) {}

    void check() {
        if (client.validateConnection()) {
            Serial.print("Connected to InfluxDB: ");
            Serial.println(client.getServerUrl());
        } else {
            Serial.print("InfluxDB connection failed: ");
            Serial.println(client.getLastErrorMessage());
        }
    }

    void record() {
        uint8_t i = 0;
        while(owm && owm[i] != NULL) {
            record_weather(owm[i]);
            ++i;
        }
        if(sensor) record_local();
    }

    void record(bool w, bool s) {
        uint8_t i = 0;
        while(w && owm && owm[i] != NULL) {
            record_weather(owm[i]);
            ++i;
        }
        if(sensor && s) record_local();
    }


    void record_local() {
        if(!sensor) return;
        Serial.println("InfluxDB: Uploading Local Data");

        dp.clearFields();
        dp.clearTags();
        dp.addTag("device", "WESP0");
        dp.addTag("location", "local");

        dp.addField("temperature", float(sensor->temp));
        dp.addField("pressure", int32_t(sensor->pres));
        dp.addField("humidity", int32_t(sensor->hum));
        dp.addField("temperature_feel", float(sensor->heatidx));

        dp.addField("uv", sensor->uv);
        dp.addField("uvi", sensor->uvi);


        dp.addField("light_full", sensor->light_full);
        dp.addField("light_vis", sensor->light_vis);
        dp.addField("light_ir", sensor->light_ir);
        dp.addField("light_lux", sensor->light_lux);

        dp.addField("voc", sensor->voci);

        dp.addField("pm10_standard", sensor->pmd.pm10_standard);
        dp.addField("pm25_standard", sensor->pmd.pm25_standard);
        dp.addField("pm100_standard", sensor->pmd.pm100_standard);
        dp.addField("pm10_env", sensor->pmd.pm10_env);
        dp.addField("pm25_env", sensor->pmd.pm25_env);
        dp.addField("pm100_env", sensor->pmd.pm100_env);
        dp.addField("particles_03um", sensor->pmd.particles_03um);
        dp.addField("particles_05um", sensor->pmd.particles_05um);
        dp.addField("particles_10um", sensor->pmd.particles_10um);
        dp.addField("particles_25um", sensor->pmd.particles_25um);
        dp.addField("particles_50um", sensor->pmd.particles_50um);
        dp.addField("particles_100um", sensor->pmd.particles_100um);

        client.writePoint(dp);
        Serial.println("InfluxDB: OK");
    }

    void record_weather() {
        record(true,false);
    }

    void record_weather(OWM* owm) {
        if(!owm) return;
        Serial.println("InfluxDB: Uploading OWM Data");
        if(!owm->valid_weather) {
            Serial.println("InfluxDB: Error, not valid weather");
            return;
        }

        JsonObject weather_0 = owm->weather["weather"][0];
        JsonObject weather_main = owm->weather["main"];
        JsonObject weather_sys = owm->weather["sys"];
        if(!weather_0 || !weather_main || !weather_sys ) return;

        dp.clearFields();
        dp.clearTags();
        dp.addTag("device", "WESP0");
        dp.addTag("location", owm->location);

        dp.addField("temperature", float(weather_main["temp"]));
        dp.addField("temperature_feel",float(weather_main["feels_like"]));
        dp.addField("pressure",int32_t(weather_main["pressure"]));
        dp.addField("humidity",int32_t(weather_main["humidity"]));


        JsonObject weather_wind = owm->weather["wind"];
        dp.addField("wind_speed",weather_wind?float(weather_wind["speed"]):0.0);
        dp.addField("wind_dir",weather_wind?float(weather_wind["deg"]):0.0);
        dp.addField("wind_gust",weather_wind?float(weather_wind["gust"]):0.0);

        dp.addField("sunrise", uint64_t(weather_sys["sunrise"]));
        dp.addField("sunset",uint64_t(weather_sys["sunset"]));
        dp.addField("suntime",uint64_t(weather_sys["sunset"])-uint64_t(weather_sys["sunrise"]));


        JsonObject weather_rain = owm->weather["rain"];
        dp.addField("precipitation_rain_1h",weather_rain?float(weather_rain["1h"]):0.0);
        dp.addField("precipitation_rain_3h",weather_rain?float(weather_rain["3h"]):0.0);

        JsonObject weather_snow = owm->weather["snow"];
        dp.addField("precipitation_snow_1h",weather_snow?float(weather_snow["1h"]):0.0);
        dp.addField("precipitation_snow_3h",weather_snow?float(weather_snow["3h"]):0.0);

        client.writePoint(dp);
        Serial.println("InfluxDB: OK");
    }


private:
    OWM** owm;
    Sensor* sensor;

    InfluxDBClient  client = InfluxDBClient(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN, cert);
    Point dp = Point("environment");
};

#endif