/** @file Logger.c
 *
 *  @ingroup ippToPsps
 *
 *  Source for all methods in the Logger class
 *
 *  @author IfA
 *  Copyright 2011 Institute for Astronomy, University of Hawaii
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
       #include <sys/time.h>

#include "Logger.h"

/**
  Destructor
  */
static void destroy(Logger* this) {

    struct timeval stopTime;
    gettimeofday(&stopTime, 0);
    double secs = (double)(stopTime.tv_sec-this->startTime.tv_sec);

    this->print(this, MSG_INFO, "Logger", 
            "Completed in %.1f %s\n",
            (secs<60.0) ? secs : (secs/60.0),
            (secs<60.0) ? "sec(s)" : "min(s)");

    this->print(this, MSG_DEBUG, "Logger", "Destructor\n");
    free(this);
}

/**
  Prints a message
  */
static void print(void* this, const int8_t typeInt, const char* class, const char* fmt, ...) {

    Logger* logger = (Logger*)this;

    va_list args;
    va_start(args, fmt);
    char msg_fmt[1000];

    // get message-type string
    char typeStr[20];
    switch(typeInt) {

        case MSG_INFO:
            sprintf(typeStr, "INFO");
            break;
        case MSG_ERROR:
            sprintf(typeStr, "ERROR");
            break;
        case MSG_DEBUG:
            if (!logger->showDebug) return;
            sprintf(typeStr, "DEBUG");
            break;
        default:
            break;
    }

    // get time string
    char timeStr[30];
    time_t now = time(NULL);
    struct tm tim = *(localtime(&now));
    strftime(timeStr, 30, "%Y/%m/%d %H:%M:%S",&tim);

    if (typeInt == MSG_NONE)
        sprintf(msg_fmt, "%s", fmt);
    else
        sprintf(msg_fmt, "%18s | %6s | %15s | %s ", timeStr, typeStr, class,  fmt);


    // write either to file or stdout
    if(logger->file == NULL) vprintf(msg_fmt, args);
    else vfprintf(logger->file, msg_fmt, args);
}

/**
  Constructor. 

  Returns a new Logger object.
  
  path      - path to file where log should be saved, otherwise stdout is used
  showDebug - show debug messages or not 
  */
Logger* new_Logger(const char* path, const int8_t showDebug) {

    Logger* this = (Logger*)calloc(1, sizeof(Logger));

    this->file = NULL;
    this->showDebug = showDebug;
    gettimeofday(&this->startTime, 0);

    // open a file to write to
    if (path != NULL) this->file = fopen(path, "w+");

    print(this, MSG_DEBUG, "Logger", "Constructor\n");
    print(this, MSG_INFO, "Logger", "Starting timer\n");

    if (path != NULL) { 

        if (this->file == NULL)
            print(this, MSG_ERROR, "Logger", "Cannot open file for writing here '%s'\n", path);
        else
            printf("**** Saving log to '%s'\n", path);
    }

    // method pointers
    this->print = print;
    this->destroy = destroy;

    return this;
}

