// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/log.h"

#include "vm/flags.h"
#include "vm/isolate.h"
#include "vm/thread.h"

namespace dart {

DEFINE_FLAG(bool, force_log_flush, false, "Always flush log messages.");

DEFINE_FLAG(charp,
            isolate_log_filter,
            NULL,
            "Log isolates whose name include the filter. "
            "Default: service isolate log messages are suppressed "
            "(specify 'vm-service' to log them).");

Log::Log(LogPrinter printer)
    : printer_(printer), manual_flush_(0), buffer_(0) {}


Log::~Log() {
  // Did someone enable manual flushing and then forgot to Flush?
  ASSERT(cursor() == 0);
}


Log* Log::Current() {
  Thread* thread = Thread::Current();
  if (thread == NULL) {
    OSThread* os_thread = OSThread::Current();
    ASSERT(os_thread != NULL);
    return os_thread->log();
  }
  Isolate* isolate = thread->isolate();
  if (isolate != NULL && Log::ShouldLogForIsolate(isolate)) {
    OSThread* os_thread = thread->os_thread();
    ASSERT(os_thread != NULL);
    return os_thread->log();
  } else {
    return Log::NoOpLog();
  }
}


void Log::Print(const char* format, ...) {
  if (this == NoOpLog()) {
    return;
  }

  va_list args;
  va_start(args, format);
  VPrint(format, args);
  va_end(args);
}


void Log::VPrint(const char* format, va_list args) {
  if (this == NoOpLog()) {
    return;
  }

  // Measure.
  va_list measure_args;
  va_copy(measure_args, args);
  intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
  va_end(measure_args);

  // Print.
  char* buffer = reinterpret_cast<char*>(malloc(len + 1));
  va_list print_args;
  va_copy(print_args, args);
  OS::VSNPrint(buffer, (len + 1), format, print_args);
  va_end(print_args);

  // Append.
  // NOTE: does not append the '\0' character.
  for (intptr_t i = 0; i < len; i++) {
    buffer_.Add(buffer[i]);
  }
  free(buffer);

  if ((manual_flush_ == 0) || FLAG_force_log_flush) {
    Flush();
  }
}


void Log::Flush(const intptr_t cursor) {
  if (this == NoOpLog()) {
    return;
  }
  if (buffer_.is_empty()) {
    return;
  }
  if (buffer_.length() <= cursor) {
    return;
  }
  TerminateString();
  const char* str = &buffer_[cursor];
  ASSERT(str != NULL);
  printer_("%s", str);
  buffer_.TruncateTo(cursor);
}


void Log::Clear() {
  if (this == NoOpLog()) {
    return;
  }
  buffer_.TruncateTo(0);
}


intptr_t Log::cursor() const {
  return buffer_.length();
}


bool Log::ShouldLogForIsolate(const Isolate* isolate) {
  if (FLAG_isolate_log_filter == NULL) {
    if (isolate->is_service_isolate()) {
      // By default, do not log for the service isolate.
      return false;
    }
    return true;
  }
  const char* name = isolate->name();
  ASSERT(name != NULL);
  if (strstr(name, FLAG_isolate_log_filter) == NULL) {
    // Filter does not match, do not log for this isolate.
    return false;
  }
  return true;
}


Log Log::noop_log_;
Log* Log::NoOpLog() {
  return &noop_log_;
}


void Log::TerminateString() {
  if (this == NoOpLog()) {
    return;
  }
  buffer_.Add('\0');
}


void Log::EnableManualFlush() {
  if (this == NoOpLog()) {
    return;
  }
  manual_flush_++;
}


void Log::DisableManualFlush() {
  if (this == NoOpLog()) {
    return;
  }

  manual_flush_--;
  ASSERT(manual_flush_ >= 0);
  if (manual_flush_ == 0) {
    Flush();
  }
}


void LogBlock::Initialize() {
  log_->EnableManualFlush();
}


LogBlock::~LogBlock() {
  log_->Flush(cursor_);
  log_->DisableManualFlush();
}

}  // namespace dart
