//  BlockyFroggy
//  Copyright © 2017 John Ryland.
//  All rights reserved.
#include "SystemLogger.h"
#include "Utilities.h"
#include <cstdio>
#include <thread>
#include <string>
#include <cstdlib>
#include <unistd.h>
#import <Foundation/NSString.h>


extern "C" void LogMessageRawF(const char *filename, int lineNumber, const char *functionName, NSString *domain, int level, NSString *message);


void SystemLogger(enum LogLevel a_level, const char* a_tag,
                  const char* a_file, const char* a_function, int a_line, const char* a_fmt, va_list a_args)
{
  // Old way which does multiple heap allocations
  //std::string msg = vFormattedString(a_fmt, a_args);
  //std::string fmt = formattedString("[%s] %s (%i): %s", a_tag, baseName(a_file).c_str(), a_line, msg.c_str());

  // New way only using the stack
  va_list args2;
  va_copy(args2, a_args);
  size_t msgSiz = std::vsnprintf(nullptr, 0, a_fmt, a_args) + 1;
  char msg[msgSiz];
  ::vsnprintf(msg, msgSiz, a_fmt, args2);
  va_end(args2);

//  char msg[StackFormat::vsize(a_fmt, a_args)];
//  StackFormat::vstring(msg, a_fmt, a_args);
  const char* baseName = Utilities::baseNameCStr(a_file);
  char fmt[Utilities::StackFormat::size("[%s] %s (%i): %s", a_tag, baseName, a_line, msg)];
  Utilities::StackFormat::string(fmt, "[%s] %s (%i): %s", a_tag, baseName, a_line, msg);

  int levelMap[] = { 4, 3, 2, 1, 0 };
  LogMessageRawF(a_file, a_line, a_function, [NSString stringWithUTF8String:a_tag], levelMap[a_level], [NSString stringWithUTF8String:msg /*.c_str()*/ ]);

#if 1
  NSLog(@"%@", [NSString stringWithUTF8String:fmt /*.c_str()*/ ]);
#else
  static std::mutex logMutex;
  logMutex.lock();
  printf("%s %s[%i:%i] %s\n", longFormatDateTime().c_str(), programName().c_str(), getpid(),
         pthread_mach_thread_np(pthread_self()), fmt /*.c_str()*/ );
  logMutex.unlock();
#endif
}

