/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmMessenger.h"

#include "cmDocumentationFormatter.h"
#include "cmMessageMetadata.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

#if !defined(CMAKE_BOOTSTRAP)
#  include "cmsys/SystemInformation.hxx"
#endif

#include <sstream>
#include <utility>

#include "cmsys/Terminal.h"

#ifdef CMake_ENABLE_DEBUGGER
#  include "cmDebuggerAdapter.h"
#endif

MessageType cmMessenger::ConvertMessageType(MessageType t) const
{
  if (t == MessageType::AUTHOR_WARNING || t == MessageType::AUTHOR_ERROR) {
    if (this->GetDevWarningsAsErrors()) {
      return MessageType::AUTHOR_ERROR;
    }
    return MessageType::AUTHOR_WARNING;
  }
  if (t == MessageType::DEPRECATION_WARNING ||
      t == MessageType::DEPRECATION_ERROR) {
    if (this->GetDeprecatedWarningsAsErrors()) {
      return MessageType::DEPRECATION_ERROR;
    }
    return MessageType::DEPRECATION_WARNING;
  }
  return t;
}

bool cmMessenger::IsMessageTypeVisible(MessageType t) const
{
  if (t == MessageType::DEPRECATION_ERROR) {
    return this->GetDeprecatedWarningsAsErrors();
  }
  if (t == MessageType::DEPRECATION_WARNING) {
    return !this->GetSuppressDeprecatedWarnings();
  }
  if (t == MessageType::AUTHOR_ERROR) {
    return this->GetDevWarningsAsErrors();
  }
  if (t == MessageType::AUTHOR_WARNING) {
    return !this->GetSuppressDevWarnings();
  }

  return true;
}

static bool printMessagePreamble(MessageType t, std::ostream& msg)
{
  // Construct the message header.
  if (t == MessageType::FATAL_ERROR) {
    msg << "CMake Error";
  } else if (t == MessageType::INTERNAL_ERROR) {
    msg << "CMake Internal Error (please report a bug)";
  } else if (t == MessageType::LOG) {
    msg << "CMake Debug Log";
  } else if (t == MessageType::DEPRECATION_ERROR) {
    msg << "CMake Deprecation Error";
  } else if (t == MessageType::DEPRECATION_WARNING) {
    msg << "CMake Deprecation Warning";
  } else if (t == MessageType::AUTHOR_WARNING) {
    msg << "CMake Warning (dev)";
  } else if (t == MessageType::AUTHOR_ERROR) {
    msg << "CMake Error (dev)";
  } else {
    msg << "CMake Warning";
  }
  return true;
}

static int getMessageColor(MessageType t)
{
  switch (t) {
    case MessageType::INTERNAL_ERROR:
    case MessageType::FATAL_ERROR:
    case MessageType::AUTHOR_ERROR:
      return cmsysTerminal_Color_ForegroundRed;
    case MessageType::AUTHOR_WARNING:
    case MessageType::WARNING:
      return cmsysTerminal_Color_ForegroundYellow;
    default:
      return cmsysTerminal_Color_Normal;
  }
}

static void printMessageText(std::ostream& msg, std::string const& text)
{
  msg << ":\n";
  cmDocumentationFormatter formatter;
  formatter.SetIndent(2u);
  formatter.PrintFormatted(msg, text);
}

static void displayMessage(MessageType t, std::ostringstream& msg)
{
  // Add a note about warning suppression.
  if (t == MessageType::AUTHOR_WARNING) {
    msg << "This warning is for project developers.  Use -Wno-dev to suppress "
           "it.";
  } else if (t == MessageType::AUTHOR_ERROR) {
    msg << "This error is for project developers. Use -Wno-error=dev to "
           "suppress it.";
  }

  // Add a terminating blank line.
  msg << "\n";

#if !defined(CMAKE_BOOTSTRAP)
  // Add a C++ stack trace to internal errors.
  if (t == MessageType::INTERNAL_ERROR) {
    std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0);
    if (!stack.empty()) {
      if (cmHasLiteralPrefix(stack, "WARNING:")) {
        stack = "Note:" + stack.substr(8);
      }
      msg << stack << "\n";
    }
  }
#endif

  // Output the message.
  cmMessageMetadata md;
  md.desiredColor = getMessageColor(t);
  if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR ||
      t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) {
    cmSystemTools::SetErrorOccurred();
    md.title = "Error";
    cmSystemTools::Message(msg.str(), md);
  } else {
    md.title = "Warning";
    cmSystemTools::Message(msg.str(), md);
  }
}

namespace {
void PrintCallStack(std::ostream& out, cmListFileBacktrace bt,
                    cm::optional<std::string> const& topSource)
{
  // The call stack exists only if we have at least two calls on top
  // of the bottom.
  if (bt.Empty()) {
    return;
  }
  bt = bt.Pop();
  if (bt.Empty()) {
    return;
  }

  bool first = true;
  for (; !bt.Empty(); bt = bt.Pop()) {
    cmListFileContext lfc = bt.Top();
    if (lfc.Name.empty() &&
        lfc.Line != cmListFileContext::DeferPlaceholderLine) {
      // Skip this whole-file scope.  When we get here we already will
      // have printed a more-specific context within the file.
      continue;
    }
    if (first) {
      first = false;
      out << "Call Stack (most recent call first):\n";
    }
    if (topSource) {
      lfc.FilePath = cmSystemTools::RelativeIfUnder(*topSource, lfc.FilePath);
    }
    out << "  " << lfc << "\n";
  }
}
}

void cmMessenger::IssueMessage(MessageType t, const std::string& text,
                               const cmListFileBacktrace& backtrace) const
{
  bool force = false;
  // override the message type, if needed, for warnings and errors
  MessageType override = this->ConvertMessageType(t);
  if (override != t) {
    t = override;
    force = true;
  }

  if (force || this->IsMessageTypeVisible(t)) {
    this->DisplayMessage(t, text, backtrace);
  }
}

void cmMessenger::DisplayMessage(MessageType t, const std::string& text,
                                 const cmListFileBacktrace& backtrace) const
{
  std::ostringstream msg;
  if (!printMessagePreamble(t, msg)) {
    return;
  }

  // Add the immediate context.
  this->PrintBacktraceTitle(msg, backtrace);

  printMessageText(msg, text);

  // Add the rest of the context.
  PrintCallStack(msg, backtrace, this->TopSource);

  displayMessage(t, msg);

#ifdef CMake_ENABLE_DEBUGGER
  if (DebuggerAdapter != nullptr) {
    DebuggerAdapter->OnMessageOutput(t, msg.str());
  }
#endif
}

void cmMessenger::PrintBacktraceTitle(std::ostream& out,
                                      cmListFileBacktrace const& bt) const
{
  // The title exists only if we have a call on top of the bottom.
  if (bt.Empty()) {
    return;
  }
  cmListFileContext lfc = bt.Top();
  if (this->TopSource) {
    lfc.FilePath =
      cmSystemTools::RelativeIfUnder(*this->TopSource, lfc.FilePath);
  }
  out << (lfc.Line ? " at " : " in ") << lfc;
}

void cmMessenger::SetTopSource(cm::optional<std::string> topSource)
{
  this->TopSource = std::move(topSource);
}
