// Copyright 2020 The Fuchsia 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 "status.h"

#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>

#include <memory>
#include <string>
#include <utility>

#include "src/lib/fxl/strings/string_printf.h"
#include "util.h"

namespace hwstress {

LogLevel LogLevelFromString(const std::string& value) {
  std::string value_lower(value);
  std::for_each(value_lower.begin(), value_lower.end(), [](char& c) { c = std::tolower(c); });

  if (value_lower == "terse") {
    return LogLevel::kTerse;
  }
  if (value_lower == "normal") {
    return LogLevel::kNormal;
  }
  if (value_lower == "verbose") {
    return LogLevel::kVerbose;
  }
  return LogLevel::kInvalid;
}

namespace {

// Return a copy of |s| with newlines stripped from it.
std::string StripNewlines(std::string_view s) {
  std::string result;
  result.reserve(s.size());
  for (size_t i = 0; i < s.size(); i++) {
    if (s[i] != '\n') {
      result.push_back(s[i]);
    }
  }
  return result;
}
}  // namespace

StatusLine::StatusLine(LogLevel level) : log_level_(level) {}

void StatusLine::Log(std::string_view s) {
  if (log_level_ == LogLevel::kTerse) {
    return;
  }
  // Remove any status already on the current line.
  ClearLineIfNeeded();

  // Log the current line, adding a trailing newline if needed.
  printf("%*s", static_cast<int>(s.size()), s.data());
  if (s.back() != '\n') {
    printf("\n");
  }
  fflush(stdout);

  // Re-display the current status.
  PrintStatus();
}

void StatusLine::Log(const char* fmt, va_list ap) {
  std::string s = fxl::StringVPrintf(fmt, ap);
  Log(std::string_view(s.data(), s.size()));
}

void StatusLine::Log(const char* fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  Log(fmt, ap);
  va_end(ap);
}

void StatusLine::Set(std::string_view status) {
  // If the new value matches the old, we have nothing to do.
  if (status == current_status_ || log_level_ == LogLevel::kTerse) {
    return;
  }

  // Otherwise, clear off the old status and print out the new.
  ClearLineIfNeeded();
  current_status_ = StripNewlines(status);
  PrintStatus();
}

void StatusLine::Set(const char* fmt, va_list ap) {
  std::string s = fxl::StringVPrintf(fmt, ap);
  Set(std::string_view(s.data(), s.size()));
}

void StatusLine::Set(const char* fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  Set(fmt, ap);
  va_end(ap);
}

void StatusLine::Verbose(const char* fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  if (log_level_ == LogLevel::kVerbose) {
    Log(fmt, ap);
  }
  va_end(ap);
}

void StatusLine::Verbose(std::string_view status) {
  if (log_level_ == LogLevel::kVerbose) {
    Log(status);
  }
}

// Remove the status line from the console.
void StatusLine::ClearLineIfNeeded() {
  if (!line_needs_clear_) {
    return;
  }
  // "\r" and ANSI escape code for clearing the current line.
  printf("\r\033[2K");
  line_needs_clear_ = false;
}

// Print |current_status_| to the console.
void StatusLine::PrintStatus() {
  if (current_status_.empty()) {
    return;
  }
  printf("%s", current_status_.c_str());
  fflush(stdout);
  line_needs_clear_ = true;
}

}  // namespace hwstress
