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

#include <utility>
#include <vector>

#include <cm3p/cppdap/optional.h>
#include <cm3p/cppdap/session.h>
#include <cm3p/cppdap/types.h>

#include "cmDebuggerProtocol.h"
#include "cmMessageType.h"

namespace cmDebugger {

cmDebuggerExceptionManager::cmDebuggerExceptionManager(
  dap::Session* dapSession)
  : DapSession(dapSession)
{
  // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_SetExceptionBreakpoints
  DapSession->registerHandler(
    [&](dap::SetExceptionBreakpointsRequest const& request) {
      return HandleSetExceptionBreakpointsRequest(request);
    });

  // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_ExceptionInfo
  DapSession->registerHandler([&](dap::ExceptionInfoRequest /*unused*/) {
    return HandleExceptionInfoRequest();
  });

  ExceptionMap[MessageType::FATAL_ERROR] =
    cmDebuggerExceptionFilter{ "FATAL_ERROR", "Fatal error" };
  ExceptionMap[MessageType::INTERNAL_ERROR] =
    cmDebuggerExceptionFilter{ "INTERNAL_ERROR", "Internal error" };
  ExceptionMap[MessageType::MESSAGE] =
    cmDebuggerExceptionFilter{ "MESSAGE", "Other messages" };
  ExceptionMap[MessageType::WARNING] =
    cmDebuggerExceptionFilter{ "WARNING", "Warning" };
  ExceptionMap[MessageType::LOG] =
    cmDebuggerExceptionFilter{ "LOG", "Debug log" };
  RaiseExceptions["FATAL_ERROR"] = true;
  RaiseExceptions["INTERNAL_ERROR"] = true;
}

dap::SetExceptionBreakpointsResponse
cmDebuggerExceptionManager::HandleSetExceptionBreakpointsRequest(
  dap::SetExceptionBreakpointsRequest const& request)
{
  std::unique_lock<std::mutex> lock(Mutex);
  dap::SetExceptionBreakpointsResponse response;
  RaiseExceptions.clear();
  for (auto const& filter : request.filters) {
    RaiseExceptions[filter] = true;
  }

  return response;
}

dap::ExceptionInfoResponse
cmDebuggerExceptionManager::HandleExceptionInfoRequest()
{
  std::unique_lock<std::mutex> lock(Mutex);

  dap::ExceptionInfoResponse response;
  if (TheException.has_value()) {
    response.exceptionId = TheException->Id;
    response.breakMode = "always";
    response.description = TheException->Description;
    TheException = cm::nullopt;
  }
  return response;
}

void cmDebuggerExceptionManager::HandleInitializeRequest(
  dap::CMakeInitializeResponse& response)
{
  std::unique_lock<std::mutex> lock(Mutex);
  response.supportsExceptionInfoRequest = true;

  dap::array<dap::ExceptionBreakpointsFilter> exceptionBreakpointFilters;
  for (auto& pair : ExceptionMap) {
    dap::ExceptionBreakpointsFilter filter;
    filter.filter = pair.second.Filter;
    filter.label = pair.second.Label;
    filter.def = RaiseExceptions[filter.filter];
    exceptionBreakpointFilters.emplace_back(filter);
  }

  response.exceptionBreakpointFilters = exceptionBreakpointFilters;
}

cm::optional<dap::StoppedEvent>
cmDebuggerExceptionManager::RaiseExceptionIfAny(MessageType t,
                                                std::string const& text)
{
  cm::optional<dap::StoppedEvent> maybeStoppedEvent;
  std::unique_lock<std::mutex> lock(Mutex);
  if (RaiseExceptions[ExceptionMap[t].Filter]) {
    dap::StoppedEvent stoppedEvent;
    stoppedEvent.allThreadsStopped = true;
    stoppedEvent.reason = "exception";
    stoppedEvent.description = "Pause on exception";
    stoppedEvent.text = text;
    TheException = cmDebuggerException{ ExceptionMap[t].Filter, text };
    maybeStoppedEvent = std::move(stoppedEvent);
  }

  return maybeStoppedEvent;
}

void cmDebuggerExceptionManager::ClearAll()
{
  std::unique_lock<std::mutex> lock(Mutex);
  RaiseExceptions.clear();
}

} // namespace cmDebugger
