#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <WiFiClient.h>

// WiFi-asetukset
const char* ssid = "aalto open";
const char* password = "";

// MQTT-asetukset
const char* mqtt_server = "public.cloud.shiftr.io";
const int mqtt_port = 1883;
const char* mqtt_user = "YOUR_SHIFTR_USERNAME";
const char* mqtt_password = "YOUR_SHIFTR_PASSWORD";
const char* mqtt_topic = "esp8266/data";

// Web-palvelin portti 80
ESP8266WebServer server(80);
WiFiClient espClient;
PubSubClient mqtt(espClient);

// Sensoriarvot (esimerkki)
float temperature = 25.5;
float humidity = 60.0;
float pressure = 1013.2;

void setup() {
    Serial.begin(115200);
    
    // WiFi-yhteyden muodostaminen
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());

    // MQTT-asetukset
    mqtt.setServer(mqtt_server, mqtt_port);
    mqtt.setCallback(mqttCallback);

    // Web-palvelimen reitit
    setupWebServer();
    server.begin();
}

void loop() {
    server.handleClient();
    
    // MQTT-yhteyden ylläpito
    if (!mqtt.connected()) {
        reconnectMQTT();
    }
    mqtt.loop();

    // Päivitä sensoriarvot (esimerkki)
    updateSensorValues();
}

void setupWebServer() {
    // Tarjoa UI-sivu
    server.on("/", HTTP_GET, []() {
        File file = SPIFFS.open("/ui.html", "r");
        server.streamFile(file, "text/html");
        file.close();
    });

    // WiFi-asetusten tallennus
    server.on("/wifi", HTTP_POST, []() {
        String ssid = server.arg("ssid");
        String password = server.arg("password");
        // Tallenna asetukset
        server.send(200, "text/plain", "Asetukset tallennettu");
    });

    // Sensoriarvojen haku
    server.on("/sensors", HTTP_GET, []() {
        StaticJsonDocument<200> doc;
        doc["temperature"] = temperature;
        doc["humidity"] = humidity;
        doc["pressure"] = pressure;
        
        String response;
        serializeJson(doc, response);
        server.send(200, "application/json", response);
    });

    // Sähkön hinnan haku (esimerkki)
    server.on("/electricity-price", HTTP_GET, []() {
        StaticJsonDocument<1024> doc;
        JsonArray times = doc.createNestedArray("times");
        JsonArray prices = doc.createNestedArray("prices");
        
        // Esimerkki 24 tunnin datasta
        for(int i = 0; i < 24; i++) {
            times.add(String(i) + ":00");
            prices.add(random(50, 200) / 10.0); // Satunnainen hinta 5-20 c/kWh
        }
        
        String response;
        serializeJson(doc, response);
        server.send(200, "application/json", response);
    });
}

void mqttCallback(char* topic, byte* payload, unsigned int length) {
    // Käsittele vastaanotettu MQTT-viesti
    char message[length + 1];
    memcpy(message, payload, length);
    message[length] = '\0';
    
    Serial.print("Vastaanotettu MQTT-viesti: ");
    Serial.println(message);
    
    // Käsittele viesti tarvittaessa
    StaticJsonDocument<200> doc;
    DeserializationError error = deserializeJson(doc, message);
    
    if (!error) {
        // Käsittele JSON-data
        if (doc.containsKey("command")) {
            String command = doc["command"];
            // Toteuta komennot
        }
    }
}

void reconnectMQTT() {
    while (!mqtt.connected()) {
        Serial.print("Yhdistetään MQTT...");
        String clientId = "ESP8266Client-";
        clientId += String(random(0xffff), HEX);
        
        if (mqtt.connect(clientId.c_str(), mqtt_user, mqtt_password)) {
            Serial.println("Yhdistetty");
            mqtt.subscribe(mqtt_topic);
        } else {
            Serial.print("Epäonnistui, rc=");
            Serial.print(mqtt.state());
            Serial.println(" Yritetään uudelleen 5s kuluttua");
            delay(5000);
        }
    }
}

void updateSensorValues() {
    // Tässä päivitetään sensoriarvot
    // Tämä on vain esimerkki - korvaa oikeilla sensoriarvoilla
    temperature += random(-10, 10) / 10.0;
    humidity += random(-5, 5) / 10.0;
    pressure += random(-2, 2) / 10.0;
    
    // Lähetä arvot MQTT:llä
    StaticJsonDocument<200> doc;
    doc["temperature"] = temperature;
    doc["humidity"] = humidity;
    doc["pressure"] = pressure;
    
    String jsonString;
    serializeJson(doc, jsonString);
    mqtt.publish(mqtt_topic, jsonString.c_str());
} 