/*
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#include <fb/log.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

#define LOG_BUFFER_SIZE 4096
static LogHandler gLogHandler;

void setLogHandler(LogHandler logHandler) {
  gLogHandler = logHandler;
}

int fb_printLog(int prio, const char *tag,  const char *fmt, ...) {
  char logBuffer[LOG_BUFFER_SIZE];

  va_list va_args;
  va_start(va_args, fmt);
  int result = vsnprintf(logBuffer, sizeof(logBuffer), fmt, va_args);
  va_end(va_args);
  if (gLogHandler != NULL) {
      gLogHandler(prio, tag, logBuffer);
  }
  __android_log_write(prio, tag, logBuffer);
  return result;
}

void logPrintByDelims(int priority, const char* tag, const char* delims,
        const char* msg, ...)
{
    va_list ap;
    char buf[32768];
    char* context;
    char* tok;

    va_start(ap, msg);
    vsnprintf(buf, sizeof(buf), msg, ap);
    va_end(ap);

    tok = strtok_r(buf, delims, &context);

    if (!tok) {
        return;
    }

    do {
        __android_log_write(priority, tag, tok);
    } while ((tok = strtok_r(NULL, delims, &context)));
}

#ifndef ANDROID

// Implementations of the basic android logging functions for non-android platforms.

static char logTagChar(int prio) {
  switch (prio) {
    default:
    case ANDROID_LOG_UNKNOWN:
    case ANDROID_LOG_DEFAULT:
    case ANDROID_LOG_SILENT:
      return ' ';
    case ANDROID_LOG_VERBOSE:
      return 'V';
    case ANDROID_LOG_DEBUG:
      return 'D';
    case ANDROID_LOG_INFO:
      return 'I';
    case ANDROID_LOG_WARN:
      return 'W';
    case ANDROID_LOG_ERROR:
      return 'E';
    case ANDROID_LOG_FATAL:
      return 'F';
  }
}

int __android_log_write(int prio, const char *tag, const char *text) {
  return fprintf(stderr, "[%c/%.16s] %s\n", logTagChar(prio), tag, text);
}

int __android_log_print(int prio, const char *tag,  const char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);

  int res = fprintf(stderr, "[%c/%.16s] ", logTagChar(prio), tag);
  res += vfprintf(stderr, "%s\n", ap);

  va_end(ap);
  return res;
}

#endif
