#define _GNU_SOURCE
#include <limits.h>
#include <stdio.h>
#include <dirent.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>

#define SENSOR 0

int read_temperature(char *filename) {
    FILE *fp;
    fp = fopen(filename, "r");

    if (fp == NULL) {
        fprintf(stderr, "Error opening file %s: %s\n", filename, strerror(errno)); // instead of perror
        return INT_MIN;
    }

    char buffer[6]; // because the file returns 5 digits + null terminator

    if (fgets(buffer, sizeof(buffer), fp) == NULL) {
        fprintf(stderr, "Error reading from %s: %s\n", filename, strerror(errno));
        fclose(fp);
        return INT_MIN;
    }

    fclose(fp);

    int temperature = strtol(buffer, NULL, 10);
    return temperature;
}

int detect_ds18b20(char *w1_id) {
    DIR *d;
    struct dirent *dir;
    d = opendir("/sys/bus/w1/devices");
    
    bool success = false;

    if (d) {
        while ((dir = readdir(d)) != NULL) {
            strcpy(w1_id, dir->d_name);
            if (strncmp("28", w1_id, 2) == 0) {
                success = true;
            }
        }
        closedir(d);
    } else {
        perror("Unable to open w1 directory");
    }

    if (success) return 0;
    return 1;
}


int read_cpu_temperature() {
    return read_temperature("/sys/class/thermal/thermal_zone0/temp");
}

int read_w1_temperature(char *w1_id) {
    char *path;
    if (asprintf(&path, "/sys/bus/w1/devices/%s/temperature", w1_id) == -1) {
        fprintf(stderr, "Unable to get path for %s: %s\n", w1_id, strerror(errno));
        return INT_MIN;
    }
    return read_temperature(path);
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("Filename required\n");
        return 1;
    }

    time_t now = time(0);
    char *line;

    int cpu_temperature;
    if ((cpu_temperature = read_cpu_temperature()) == INT_MIN) {
        perror("Failed to read cpu temperature");
        return 1;
    }
    
    if (SENSOR) {
        char w1_id[16];
        if ((detect_ds18b20(w1_id)) == 1)
            return 1;
        printf("Using sensor: %s\n", w1_id);

        int env_temperature;
        if ((env_temperature = read_w1_temperature(w1_id)) == INT_MIN) {
            perror("Failed to read env temperature");
            return 1;
        }

        asprintf(&line, "%ld,%d,%d\n", now, cpu_temperature, env_temperature);
        printf("timestamp,cpu_temp,env_temp\n%s", line);
    } else {
        asprintf(&line, "%ld,%d\n", now, cpu_temperature);
        printf("timestamp,cpu_temp\n%s", line);
    }


    FILE *fp;
    fp = fopen(argv[1], "a");

    if (fp == NULL) {
        perror("Error opening output file");
        return 1;
    }

    if (fprintf(fp, line) < 0) {
        perror("Error writing to output file");
        fclose(fp);
        return 1;
    }
    fclose(fp);
}