#include "Log.h"
#include "LogListener.h"
#include <sstream>
#include <iostream>
#include <iomanip>
#include <sys/syscall.h>
#include <unistd.h>

namespace coreutils {

  LogListener *Log::logListener = NULL;
  File *Log::logFile = NULL;
  int Log::seq = 0;

  Log::Log(LogListener *logListener) {
    this->logListener = logListener;
  }

  Log::Log(File *logFile) {
    this->logFile = logFile;
  }

  Log::Log(int level) {

    output = true;

    std::stringstream temp;
    struct timespec timex;
    clock_gettime(CLOCK_REALTIME, &timex);
    temp << timex.tv_sec << "." << std::setfill('0') << std::setw(9) << timex.tv_nsec;

    *this << temp.str();
    *this << " ";

    *this << "[" << syscall(SYS_gettid) << "]";

    switch (level) {
    case LOG_NONE:
      *this << "[NONE]  :";
      break;
    case LOG_INFO:
      *this << "[INFO]  :";
      break;
    case LOG_WARN:
      *this << "[WARN]  :";
      break;
    case LOG_EXCEPT:
      *this << "[EXCEPT]: ";
      break;
    case LOG_DEBUG_1:
      *this << "[DEBUG1]: ";
      break;
    case LOG_DEBUG_2:
      *this << "[DEBUG2]:  ";
      break;
    case LOG_DEBUG_3:
      *this << "[DEBUG3]:   ";
      break;
    case LOG_DEBUG_4:
      *this << "[DEBUG4]:    ";
      break;
    default:
      *this << "[?]     ?";
      break;
    };
  }

  Log::~Log() {

    if (output) {

      std::stringstream out;
      out << this->str() << std::endl;
      ;

      mtx.lock();

      if (logListener)
        logListener->logSend(out.str());

      if (logFile)
        logFile->write(out.str());

//      std::cout << out.str();
      ++seq;

      mtx.unlock();
    }
  }

}
