// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/log.h"

#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>

#include "starboard/client_porting/eztime/eztime.h"
#include "starboard/client_porting/poem/string_poem.h"
#include "starboard/mutex.h"
#include "starboard/system.h"
#include "starboard/thread.h"
#include "starboard/time.h"

namespace starboard {
namespace logging {

namespace {
SbLogPriority g_min_log_level = kSbLogPriorityUnknown;
SbMutex g_log_mutex = SB_MUTEX_INITIALIZER;

#if defined(COMPILER_MSVC)
#pragma optimize("", off)
#endif

void Alias(const void* /*var*/) {}

#if defined(COMPILER_MSVC)
#pragma optimize("", on)
#endif

const char* log_priority_names[] = {
    "UNKNOWN", "INFO", "WARNING", "ERROR", "FATAL",
};

}  // namespace

void SetMinLogLevel(SbLogPriority priority) {
  g_min_log_level = priority;
}

SbLogPriority GetMinLogLevel() {
#if SB_LOGGING_IS_OFFICIAL_BUILD
  return SB_LOG_FATAL;
#else
  return g_min_log_level;
#endif
}

void Break() {
  SbSystemBreakIntoDebugger();
}

std::ostream& operator<<(std::ostream& out, const Stack& stack_token) {
  int skip_frames = stack_token.skip_frames;
  if (skip_frames < 0) {
    skip_frames = 0;
  }

  void* stack[256];
  int count = SbSystemGetStack(stack, SB_ARRAY_SIZE_INT(stack));

  // Skip over DumpStack's stack frame, plus any more requested by the caller.
  for (int i = 1 + skip_frames; i < count; ++i) {
    char symbol[512];
    bool result =
        SbSystemSymbolize(stack[i], symbol, SB_ARRAY_SIZE_INT(symbol));
    out << "\t";
    if (result) {
      out << symbol;
    } else {
      out << "<unknown>";
    }
    out << " [" << stack[i] << "]\n";
  }
  return out;
}

std::ostream& operator<<(std::ostream& out, const wchar_t* wstr) {
  // We don't have any good cross-platform wide character to UTF8 converter at
  // this level in the stack, so just throwing out non-ASCII characters.
  // TODO: Convert to UTF8.
  size_t len = wcslen(wstr);
  char* buffer = new char[len + 1];
  size_t pos = 0;
  for (size_t i = 0; i < len; ++i) {
    if (wstr[i] < 128) {
      buffer[pos++] = static_cast<char>(wstr[i]);
    }
  }
  buffer[pos] = '\0';
  out << buffer;
  delete[] buffer;
  return out;
}

LogMessage::LogMessage(const char* file, int line, SbLogPriority priority)
    : priority_(priority), file_(file), line_(line) {
  Init(file, line);
}

LogMessage::~LogMessage() {
  stream_ << std::endl;
  // Output the stack trace on Fatal messages.
  if (priority_ == kSbLogPriorityFatal) {
    stream_ << Stack(1);
  }
  std::string str_newline(stream_.str());
  SbMutexAcquire(&g_log_mutex);
  SbLog(priority_, str_newline.c_str());
  SbMutexRelease(&g_log_mutex);
  if (priority_ == kSbLogPriorityFatal) {
    // Ensure the first characters of the string are on the stack so they
    // are contained in minidumps for diagnostic purposes.
    char str_stack[1024];
    const size_t copy_bytes =
        std::min(SB_ARRAY_SIZE(str_stack), str_newline.length() + 1);
    PoemStringCopyN(str_stack, str_newline.c_str(),
                    static_cast<int>(copy_bytes));

    Alias(str_stack);
    Break();
  }
}

void LogMessage::Init(const char* file, int line) {
  std::string filename(file);
  size_t last_slash_pos = filename.find_last_of("\\/");
  if (last_slash_pos != std::string::npos) {
    filename.erase(0, last_slash_pos + 1);
  }

  stream_ << '[';
  stream_ << SbThreadGetId() << ':';
  EzTimeValue time_value;
  EzTimeValueGetNow(&time_value, NULL);
  EzTimeT t = time_value.tv_sec;
  struct EzTimeExploded local_time = {0};
  EzTimeTExplodeLocal(&t, &local_time);
  struct EzTimeExploded* tm_time = &local_time;
  stream_ << std::setfill('0') << std::setw(2) << 1 + tm_time->tm_mon
          << std::setw(2) << tm_time->tm_mday << '/' << std::setw(2)
          << tm_time->tm_hour << std::setw(2) << tm_time->tm_min << std::setw(2)
          << tm_time->tm_sec << '.' << std::setw(6) << time_value.tv_usec
          << ':';
  stream_ << log_priority_names[priority_];
  stream_ << ":" << filename << "(" << line << ")] ";
  message_start_ = stream_.tellp();
}

}  // namespace logging
}  // namespace starboard
