#include <stdio.h>
#include <wiringPi.h>
#include "dht22.h"
#include <stdlib.h>
#include <unistd.h>
#include "sendmysql.h"
#include "configreader.h"
#include "restcurl.h"
#include <string.h>
#include "calculate.h" //for comparing the nodes
#include <math.h>

//Temporary include
#include "calculate.h"

void freeNodeLinkedList(sensornode *node) {
    void *victim;
    if (node != NULL) {
        while (node) {
            victim = node;
            node = node->next;
            free(victim);
        }
    }
}



int main(void) {
    if (wiringPiSetup () == -1)
        exit(EXIT_FAILURE) ;
    
    if (setuid(getuid()) < 0)
    {
        perror("Dropping privileges failed\n");
        exit(EXIT_FAILURE);
    }
    
    cfginit();
    
    sensor data; //data of the raspberrypi
    data.node_id = 0; //Node ID 0 --> RaspberryPi
    int i;
    for (i = 0; i < cfgreadpinamount(); i++) {
        data.pin = cfgreadpinnumber(i);
        //getData(&data);
        //printf("Pin: %i, %.2f, %.2f\n", data.pin, data.temperature, data.humidity);
        //insertData(&data);
    }
    
    sensornode nodes; //Settings of ESP8266 sensor nodes
    int nodecount = 0;
    printf("Reading Sensornodes\n");
    cfgreadsensornodes(&nodes, nodecount); //read settings
    printf("Reading Sensornodes done Nodecount: %i\n", nodecount);
    sensor nodedata[nodecount]; //Should be a linked list for further data usage
    sensornode *currentNode = &nodes;
    //nodedata.pin = 0; //This data isn't relevant for a sensornode
    printf("First IP: %s\n", nodes.ip);
    
    for (i = 0; i <= nodecount; i++) {
        //start rest requests
        nodedata[i].pin = 0; //This data isn't relevant for a sensornode
        strcpy(nodedata[i].ip, currentNode->ip);
        if (getRestSensor(&nodedata[i])) {
            nodedata[i].isoutside = currentNode->isoutside; //copy the boolean value
            printf("Acquiring rest response\n");
        
            printf("Temperature: %f, Humidity: %f, NodeID: %i, Outside: %s, AbsoluteHumidity: %f\n", nodedata[i].temperature, nodedata[i].humidity, nodedata[i].node_id, nodedata[i].isoutside ? "Yes" : "No", absoluteHumidity(&nodedata[i]));
        
            //Insert data into database
            printf("Insert data into stats table\n");
            insertData(&nodedata[i]);
        }
                
        currentNode = currentNode->next;
    }
    
    //Compare the sensors
    //int comparecount = cfgreadcompareidamount();
    int j, k;
    for (j = 0; j < nodecount; j++) {
        for (k = 0; k < nodecount; k++) {
            if (j != k && nodedata[j].isoutside == 0 && nodedata[k].isoutside == 1) { //Compare all inside nodes with all outside nodes
                printf("Node %i (%s) - Node %i (%s): %s\n", nodedata[j].node_id, nodedata[j].isoutside ? "Inside" : "Outside", \
                nodedata[k].node_id, nodedata[k].isoutside ? "Inside" : "Outside", \
                compareSensors(&nodedata[j], &nodedata[k]) ? "Open the window" : "Close the window");
            }
        }
    }
    
    
    //build averages from all indoor/all outdoor sensors
    float avtemp_in = 0.0, avhum_in = 0.0;
    float avtemp_out = 0.0, avhum_out = 0.0;
    int inCount = 0, outCount = 0;
    for (j = 0; j <= nodecount; j++) {
        if (nodedata[j].isoutside == 0) {
            //This node is a indoor node
            avtemp_in += nodedata[j].temperature;
            avhum_in += nodedata[j].humidity;
            inCount++;
        } else {
            //This node is a outdoor node
            avtemp_out += nodedata[j].temperature;
            avhum_out += nodedata[j].humidity;
            outCount++;
        }
            
    }

    //Do the math
    float avgInsideTemperature = avtemp_in / inCount;
    float avgInsideHumidity = avhum_in / inCount;
    float avgOutsideTemperature = avtemp_in / outCount;
    float avgOutsideHumidity = avhum_in / outCount;
    
    //Insert the results into the database
    if (isfinite(avgInsideHumidity) && isfinite(avgInsideTemperature) && avgInsideHumidity != 0 && avgInsideTemperature != 0) {
        insertDataAverages(avgInsideTemperature, avgInsideHumidity, absoluteHumidityFloat(avgInsideTemperature, avgInsideHumidity), 0);
    }
    if (isfinite(avgOutsideHumidity) && isfinite(avgOutsideTemperature) && avgOutsideHumidity != 0 && avgOutsideTemperature != 0) {
        insertDataAverages(avgOutsideTemperature, avgOutsideHumidity, absoluteHumidityFloat(avgOutsideTemperature, avgOutsideHumidity), 1);
    }
    
    printf("Averages:\n| Inside temperature: %f\n| Inside humidity: %f\n| Outside temperature: %f\n| Outside humidity: %f\n", avgInsideTemperature, avgInsideHumidity, avgOutsideTemperature, avgOutsideHumidity);

    //free
    //freeNodeLinkedList(nodes.next);
    cfgdestroy();
    return 0;
}
