#include <stdarg.h>
#include <stdio.h>
#include <syslog.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include "cputemp2maxfreq.h"
#include "debug.h"

extern struct s_config config;
extern struct s_cpudata cpudata;

// The logger_* functions are not called directly. They are set by argparse in
// the config.logger function pointer.

// No logging at all
void logger_none(char *format,...) { }

// Logging to stdout
void logger_stdout(char *format,...)
{
 va_list args;
 struct timeval systime;
 struct tm *systime_tm;
 char timestring[255];
 time_t unixtime;

 if (config.use_unixtime==0)
 {
  gettimeofday(&systime,NULL);
  systime_tm=localtime(&systime.tv_sec);
  strftime(timestring,sizeof(timestring),"%F %T",systime_tm);
  printf("%s: ",timestring);
 } else {
  unixtime=time(NULL);
  printf("%ld: ",unixtime);
 }

 va_start(args,format);
 vprintf(format,args);
 va_end(args);
 putchar(10);
}

// Logging to syslog
void logger_syslog(char *format,...)
{
 va_list args;

 va_start(args,format);
 vsyslog(LOG_DAEMON||LOG_CRIT,format,args);
 va_end(args);
}

// Logging to kernel log buffer (/dev/kmsg)
void logger_kmsg(char *format,...)
{
 va_list args;
 FILE *kmsg;
 char buffer[255];

 kmsg=fopen("/dev/kmsg","w");
 if (kmsg!=NULL)
 {
  fprintf(kmsg,"cputemp2maxfreq: ");
  va_start(args,format);
  vfprintf(kmsg,format,args);
  va_end(args);
  putc(10,kmsg);
  fclose(kmsg);
 } else {
  va_start(args,format);
  vsnprintf(buffer,sizeof(buffer),format,args);
  va_end(args);
  strcpy(config.logger_name,"stdout");
  config.logger=&logger_stdout;
  config.logger("Failed to open /dev/kmsg, falling back to stdout logging");
  config.logger(buffer);
 }
}

// CSV logging fields:
// 1: Timestamp
// 2: CPU Minimum frequency
// 3: CPU Maximum frequency
// 4: CPU Current frequency
// 5: CPU Temperature
// 6: Target temperature
// 7: Scaling maximum frequency before increase/decrease
void csvlog_init()
{
 int exists;

 DEBUG1_LOG("Started\n");
 exists=access(config.csvlog,F_OK);
 DEBUG1_LOG("File %s exists: %d\n",config.csvlog,exists);

 if ((exists!=0) || (config.csvoverwrite==1))
 {
  DEBUG1_LOG("Creating/overwriting CSV file\n");
  config.csvfile=fopen(config.csvlog,"w");
  fputs("\"timestamp\","
        "\"CPU Minumum frequency\","
        "\"CPU Maximum frequency\","
        "\"CPU Current frequency\","
        "\"CPU Temperature\","
        "\"Target Temperature\","
        "\"Scaling maximum frequency\"\n",config.csvfile);
 } else {
  DEBUG1_LOG("Appending to CSV file\n");
  config.csvfile=fopen(config.csvlog,"a");
 }
}

// Write a single line of CSV data
void csvlog_write()
{
 struct timeval systime;
 struct tm *systime_tm;
 char timestring[255];
 time_t unixtime;

 DEBUG1_LOG("Writing data series to CSV file\n");

 if (config.use_unixtime==0)
 {
  gettimeofday(&systime,NULL);
  systime_tm=localtime(&systime.tv_sec);
  strftime(timestring,sizeof(timestring),"\"%F %T\"",systime_tm);
 } else {
  unixtime=time(NULL);
  snprintf(timestring,sizeof(timestring),"%ld",unixtime);
 }

 fprintf(config.csvfile,"%s,\"%ld\",\"%ld\",\"%ld\",\"%ld\",\"%ld\",\"%ld\"\n",timestring,cpudata.min_freq,cpudata.max_freq,cpudata.cur_freq,cpudata.cur_temp/1000,config.max_temp/1000,cpudata.scale_max);
}

// Close the CSV file
void csvlog_close()
{
 DEBUG1_LOG("Closing CSV file\n");
 fclose(config.csvfile);
 config.csvfile=NULL;
}