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

#include <chrono>
#include <cstdio>
#include <future>
#include <memory>
#include <string>

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

#include "cmDebuggerAdapter.h"
#include "cmDebuggerProtocol.h"
#include "cmVersionConfig.h"

#include "testCommon.h"
#include "testDebugger.h"

class DebuggerLocalConnection : public cmDebugger::cmDebuggerConnection
{
public:
  DebuggerLocalConnection()
    : ClientToDebugger(dap::pipe())
    , DebuggerToClient(dap::pipe())
  {
  }

  bool StartListening(std::string& errorMessage) override
  {
    errorMessage = "";
    return true;
  }
  void WaitForConnection() override {}

  std::shared_ptr<dap::Reader> GetReader() override
  {
    return ClientToDebugger;
  };

  std::shared_ptr<dap::Writer> GetWriter() override
  {
    return DebuggerToClient;
  }

  std::shared_ptr<dap::ReaderWriter> ClientToDebugger;
  std::shared_ptr<dap::ReaderWriter> DebuggerToClient;
};

bool runTest(std::function<bool(dap::Session&)> onThreadExitedEvent)
{
  std::promise<bool> debuggerAdapterInitializedPromise;
  std::future<bool> debuggerAdapterInitializedFuture =
    debuggerAdapterInitializedPromise.get_future();

  std::promise<bool> initializedEventReceivedPromise;
  std::future<bool> initializedEventReceivedFuture =
    initializedEventReceivedPromise.get_future();

  std::promise<bool> exitedEventReceivedPromise;
  std::future<bool> exitedEventReceivedFuture =
    exitedEventReceivedPromise.get_future();

  std::promise<bool> terminatedEventReceivedPromise;
  std::future<bool> terminatedEventReceivedFuture =
    terminatedEventReceivedPromise.get_future();

  std::promise<bool> threadStartedPromise;
  std::future<bool> threadStartedFuture = threadStartedPromise.get_future();

  std::promise<bool> threadExitedPromise;
  std::future<bool> threadExitedFuture = threadExitedPromise.get_future();

  std::promise<bool> disconnectResponseReceivedPromise;
  std::future<bool> disconnectResponseReceivedFuture =
    disconnectResponseReceivedPromise.get_future();

  auto futureTimeout = std::chrono::seconds(60);

  auto connection = std::make_shared<DebuggerLocalConnection>();
  std::unique_ptr<dap::Session> client = dap::Session::create();
  client->registerHandler([&](dap::InitializedEvent /*unused*/) {
    initializedEventReceivedPromise.set_value(true);
  });
  client->registerHandler([&](dap::ExitedEvent /*unused*/) {
    exitedEventReceivedPromise.set_value(true);
  });
  client->registerHandler([&](dap::TerminatedEvent const& /*unused*/) {
    terminatedEventReceivedPromise.set_value(true);
  });
  client->registerHandler([&](dap::ThreadEvent const& e) {
    if (e.reason == "started") {
      threadStartedPromise.set_value(true);
    } else if (e.reason == "exited") {
      threadExitedPromise.set_value(true);
    }
  });

  client->bind(connection->DebuggerToClient, connection->ClientToDebugger);

  ScopedThread debuggerThread([&]() -> int {
    std::shared_ptr<cmDebugger::cmDebuggerAdapter> debuggerAdapter =
      std::make_shared<cmDebugger::cmDebuggerAdapter>(
        connection, dap::file(stdout, false));

    debuggerAdapterInitializedPromise.set_value(true);
    debuggerAdapter->ReportExitCode(0);

    // Ensure the disconnectResponse has been received before
    // destructing debuggerAdapter.
    ASSERT_TRUE(disconnectResponseReceivedFuture.wait_for(futureTimeout) ==
                std::future_status::ready);
    return 0;
  });

  dap::CMakeInitializeRequest initializeRequest;
  auto initializeResponse = client->send(initializeRequest).get();
  ASSERT_TRUE(initializeResponse.response.cmakeVersion.full == CMake_VERSION);
  ASSERT_TRUE(initializeResponse.response.cmakeVersion.major ==
              CMake_VERSION_MAJOR);
  ASSERT_TRUE(initializeResponse.response.cmakeVersion.minor ==
              CMake_VERSION_MINOR);
  ASSERT_TRUE(initializeResponse.response.cmakeVersion.patch ==
              CMake_VERSION_PATCH);
  ASSERT_TRUE(initializeResponse.response.supportsExceptionInfoRequest);
  ASSERT_TRUE(
    initializeResponse.response.exceptionBreakpointFilters.has_value());
  ASSERT_TRUE(initializeResponse.response.supportsValueFormattingOptions);

  dap::LaunchRequest launchRequest;
  auto launchResponse = client->send(launchRequest).get();
  ASSERT_TRUE(!launchResponse.error);

  dap::ConfigurationDoneRequest configurationDoneRequest;
  auto configurationDoneResponse =
    client->send(configurationDoneRequest).get();
  ASSERT_TRUE(!configurationDoneResponse.error);

  ASSERT_TRUE(debuggerAdapterInitializedFuture.wait_for(futureTimeout) ==
              std::future_status::ready);
  ASSERT_TRUE(initializedEventReceivedFuture.wait_for(futureTimeout) ==
              std::future_status::ready);
  ASSERT_TRUE(threadStartedFuture.wait_for(futureTimeout) ==
              std::future_status::ready);
  ASSERT_TRUE(threadExitedFuture.wait_for(futureTimeout) ==
              std::future_status::ready);

  if (onThreadExitedEvent) {
    ASSERT_TRUE(onThreadExitedEvent(*client));
  }

  ASSERT_TRUE(exitedEventReceivedFuture.wait_for(futureTimeout) ==
              std::future_status::ready);
  ASSERT_TRUE(terminatedEventReceivedFuture.wait_for(futureTimeout) ==
              std::future_status::ready);

  dap::DisconnectRequest disconnectRequest;
  auto disconnectResponse = client->send(disconnectRequest).get();
  disconnectResponseReceivedPromise.set_value(true);
  ASSERT_TRUE(!disconnectResponse.error);

  return true;
}

bool testBasicProtocol()
{
  return runTest(nullptr);
}

bool testThreadsRequestAfterThreadExitedEvent()
{
  return runTest([](dap::Session& session) -> bool {
    // Try requesting threads again after receiving the thread exited event.
    // Some clients do this to ensure that their thread list is up-to-date.
    dap::ThreadsRequest threadsRequest;
    auto threadsResponse = session.send(threadsRequest).get();
    ASSERT_TRUE(!threadsResponse.error);

    // CMake only has one DAP thread. Once that thread exits, there should be
    // no threads left.
    ASSERT_TRUE(threadsResponse.response.threads.empty());

    return true;
  });
}

int testDebuggerAdapter(int, char*[])
{
  return runTests(
    { testBasicProtocol, testThreadsRequestAfterThreadExitedEvent });
}
