// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "brillo/syslog_logging.h"

#include <syslog.h>
#include <unistd.h>

#include <string>

// syslog.h and base/logging.h both try to #define LOG_INFO and LOG_WARNING.
// We need to #undef at least these two before including base/logging.h.  The
// others are included to be consistent.
namespace {
const int kSyslogDebug    = LOG_DEBUG;
const int kSyslogInfo     = LOG_INFO;
const int kSyslogWarning  = LOG_WARNING;
const int kSyslogError    = LOG_ERR;
const int kSyslogCritical = LOG_CRIT;

#undef LOG_INFO
#undef LOG_WARNING
#undef LOG_ERR
#undef LOG_CRIT
}  // namespace

#include <base/logging.h>

static std::string s_ident;
static std::string s_accumulated;
static bool s_accumulate;
static bool s_log_to_syslog;
static bool s_log_to_stderr;
static bool s_log_header;

static bool HandleMessage(int severity,
                          const char* /* file */,
                          int /* line */,
                          size_t message_start,
                          const std::string& message) {
  switch (severity) {
    case logging::LOG_INFO:
      severity = kSyslogInfo;
      break;

    case logging::LOG_WARNING:
      severity = kSyslogWarning;
      break;

    case logging::LOG_ERROR:
      severity = kSyslogError;
      break;

    case logging::LOG_FATAL:
      severity = kSyslogCritical;
      break;

    default:
      severity = kSyslogDebug;
      break;
  }

  const char* str;
  if (s_log_header) {
    str = message.c_str();
  } else {
    str = message.c_str() + message_start;
  }

  if (s_log_to_syslog)
    syslog(severity, "%s", str);
  if (s_accumulate)
    s_accumulated.append(str);
  return !s_log_to_stderr && severity != kSyslogCritical;
}

namespace brillo {
void SetLogFlags(int log_flags) {
  s_log_to_syslog = (log_flags & kLogToSyslog) != 0;
  s_log_to_stderr = (log_flags & kLogToStderr) != 0;
  if ((log_flags & kLogToStderrIfTty) && isatty(0))
    s_log_to_stderr = true;
  s_log_header = (log_flags & kLogHeader) != 0;
}
int GetLogFlags() {
  int flags = 0;
  flags |= (s_log_to_syslog) ? kLogToSyslog : 0;
  flags |= (s_log_to_stderr) ? kLogToStderr : 0;
  flags |= (s_log_header) ? kLogHeader : 0;
  return flags;
}
void InitLog(int init_flags) {
  logging::LoggingSettings settings;
  settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
  logging::InitLogging(settings);

  const bool kOptionPID = false;
  const bool kOptionTID = false;
  const bool kOptionTimestamp = false;
  const bool kOptionTickcount = false;
  logging::SetLogItems(
      kOptionPID, kOptionTID, kOptionTimestamp, kOptionTickcount);
  logging::SetLogMessageHandler(HandleMessage);
  SetLogFlags(init_flags);
}
void OpenLog(const char* ident, bool log_pid) {
  s_ident = ident;
  openlog(s_ident.c_str(), log_pid ? LOG_PID : 0, LOG_USER);
}
void LogToString(bool enabled) {
  s_accumulate = enabled;
}
std::string GetLog() {
  return s_accumulated;
}
void ClearLog() {
  s_accumulated.clear();
}
bool FindLog(const char* string) {
  return s_accumulated.find(string) != std::string::npos;
}
}  // namespace brillo
