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

#include <algorithm>
#include <cassert>
#include <csignal>
#include <cstdint>
#include <iostream>
#include <mutex>
#include <utility>

#include <cm/memory>
#include <cm/shared_mutex>

#include <cm3p/json/reader.h>
#include <cm3p/json/writer.h>

#include "cmsys/FStream.hxx"

#include "cmConnection.h"
#include "cmFileMonitor.h"
#include "cmJsonObjectDictionary.h"
#include "cmServerDictionary.h"
#include "cmServerProtocol.h"
#include "cmSystemTools.h"
#include "cmake.h"

void on_signal(uv_signal_t* signal, int signum)
{
  auto conn = static_cast<cmServerBase*>(signal->data);
  conn->OnSignal(signum);
}

static void on_walk_to_shutdown(uv_handle_t* handle, void* arg)
{
  (void)arg;
  assert(uv_is_closing(handle));
  if (!uv_is_closing(handle)) {
    uv_close(handle, &cmEventBasedConnection::on_close);
  }
}

class cmServer::DebugInfo
{
public:
  DebugInfo()
    : StartTime(uv_hrtime())
  {
  }

  bool PrintStatistics = false;

  std::string OutputFile;
  uint64_t StartTime;
};

cmServer::cmServer(cmConnection* conn, bool supportExperimental)
  : cmServerBase(conn)
  , SupportExperimental(supportExperimental)
{
  // Register supported protocols:
  this->RegisterProtocol(cm::make_unique<cmServerProtocol1>());
}

cmServer::~cmServer()
{
  Close();
}

void cmServer::ProcessRequest(cmConnection* connection,
                              const std::string& input)
{
  Json::Reader reader;
  Json::Value value;
  if (!reader.parse(input, value)) {
    this->WriteParseError(connection, "Failed to parse JSON input.");
    return;
  }

  std::unique_ptr<DebugInfo> debug;
  Json::Value debugValue = value["debug"];
  if (!debugValue.isNull()) {
    debug = cm::make_unique<DebugInfo>();
    debug->OutputFile = debugValue["dumpToFile"].asString();
    debug->PrintStatistics = debugValue["showStats"].asBool();
  }

  const cmServerRequest request(this, connection, value[kTYPE_KEY].asString(),
                                value[kCOOKIE_KEY].asString(), value);

  if (request.Type.empty()) {
    cmServerResponse response(request);
    response.SetError("No type given in request.");
    this->WriteResponse(connection, response, nullptr);
    return;
  }

  cmSystemTools::SetMessageCallback(
    [&request](const std::string& msg, const char* title) {
      reportMessage(msg, title, request);
    });

  if (this->Protocol) {
    this->Protocol->CMakeInstance()->SetProgressCallback(
      [&request](const std::string& msg, float prog) {
        reportProgress(msg, prog, request);
      });
    this->WriteResponse(connection, this->Protocol->Process(request),
                        debug.get());
  } else {
    this->WriteResponse(connection, this->SetProtocolVersion(request),
                        debug.get());
  }
}

void cmServer::RegisterProtocol(std::unique_ptr<cmServerProtocol> protocol)
{
  if (protocol->IsExperimental() && !this->SupportExperimental) {
    protocol.reset();
    return;
  }
  auto version = protocol->ProtocolVersion();
  assert(version.first >= 0);
  assert(version.second >= 0);
  auto it = std::find_if(
    this->SupportedProtocols.begin(), this->SupportedProtocols.end(),
    [version](const std::unique_ptr<cmServerProtocol>& p) {
      return p->ProtocolVersion() == version;
    });
  if (it == this->SupportedProtocols.end()) {
    this->SupportedProtocols.push_back(std::move(protocol));
  }
}

void cmServer::PrintHello(cmConnection* connection) const
{
  Json::Value hello = Json::objectValue;
  hello[kTYPE_KEY] = "hello";

  Json::Value& protocolVersions = hello[kSUPPORTED_PROTOCOL_VERSIONS] =
    Json::arrayValue;

  for (auto const& proto : this->SupportedProtocols) {
    auto version = proto->ProtocolVersion();
    Json::Value tmp = Json::objectValue;
    tmp[kMAJOR_KEY] = version.first;
    tmp[kMINOR_KEY] = version.second;
    if (proto->IsExperimental()) {
      tmp[kIS_EXPERIMENTAL_KEY] = true;
    }
    protocolVersions.append(tmp);
  }

  this->WriteJsonObject(connection, hello, nullptr);
}

void cmServer::reportProgress(const std::string& msg, float progress,
                              const cmServerRequest& request)
{
  if (progress < 0.0f || progress > 1.0f) {
    request.ReportMessage(msg, "");
  } else {
    request.ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg);
  }
}

void cmServer::reportMessage(const std::string& msg, const char* title,
                             const cmServerRequest& request)
{
  std::string titleString;
  if (title) {
    titleString = title;
  }
  request.ReportMessage(msg, titleString);
}

cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
{
  if (request.Type != kHANDSHAKE_TYPE) {
    return request.ReportError("Waiting for type \"" + kHANDSHAKE_TYPE +
                               "\".");
  }

  Json::Value requestedProtocolVersion = request.Data[kPROTOCOL_VERSION_KEY];
  if (requestedProtocolVersion.isNull()) {
    return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
                               "\" is required for \"" + kHANDSHAKE_TYPE +
                               "\".");
  }

  if (!requestedProtocolVersion.isObject()) {
    return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
                               "\" must be a JSON object.");
  }

  Json::Value majorValue = requestedProtocolVersion[kMAJOR_KEY];
  if (!majorValue.isInt()) {
    return request.ReportError("\"" + kMAJOR_KEY +
                               "\" must be set and an integer.");
  }

  Json::Value minorValue = requestedProtocolVersion[kMINOR_KEY];
  if (!minorValue.isNull() && !minorValue.isInt()) {
    return request.ReportError("\"" + kMINOR_KEY +
                               "\" must be unset or an integer.");
  }

  const int major = majorValue.asInt();
  const int minor = minorValue.isNull() ? -1 : minorValue.asInt();
  if (major < 0) {
    return request.ReportError("\"" + kMAJOR_KEY + "\" must be >= 0.");
  }
  if (!minorValue.isNull() && minor < 0) {
    return request.ReportError("\"" + kMINOR_KEY +
                               "\" must be >= 0 when set.");
  }

  this->Protocol =
    cmServer::FindMatchingProtocol(this->SupportedProtocols, major, minor);
  if (!this->Protocol) {
    return request.ReportError("Protocol version not supported.");
  }

  std::string errorMessage;
  if (!this->Protocol->Activate(this, request, &errorMessage)) {
    this->Protocol = nullptr;
    return request.ReportError("Failed to activate protocol version: " +
                               errorMessage);
  }
  return request.Reply(Json::objectValue);
}

bool cmServer::Serve(std::string* errorMessage)
{
  if (this->SupportedProtocols.empty()) {
    *errorMessage =
      "No protocol versions defined. Maybe you need --experimental?";
    return false;
  }
  assert(!this->Protocol);

  return cmServerBase::Serve(errorMessage);
}

cmFileMonitor* cmServer::FileMonitor() const
{
  return fileMonitor.get();
}

void cmServer::WriteJsonObject(const Json::Value& jsonValue,
                               const DebugInfo* debug) const
{
  cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
  for (auto& connection : this->Connections) {
    WriteJsonObject(connection.get(), jsonValue, debug);
  }
}

void cmServer::WriteJsonObject(cmConnection* connection,
                               const Json::Value& jsonValue,
                               const DebugInfo* debug) const
{
  Json::FastWriter writer;

  auto beforeJson = uv_hrtime();
  std::string result = writer.write(jsonValue);

  if (debug) {
    Json::Value copy = jsonValue;
    if (debug->PrintStatistics) {
      Json::Value stats = Json::objectValue;
      auto endTime = uv_hrtime();

      stats["jsonSerialization"] = double(endTime - beforeJson) / 1000000.0;
      stats["totalTime"] = double(endTime - debug->StartTime) / 1000000.0;
      stats["size"] = static_cast<int>(result.size());
      if (!debug->OutputFile.empty()) {
        stats["dumpFile"] = debug->OutputFile;
      }

      copy["zzzDebug"] = stats;

      result = writer.write(copy); // Update result to include debug info
    }

    if (!debug->OutputFile.empty()) {
      cmsys::ofstream myfile(debug->OutputFile.c_str());
      myfile << result;
    }
  }

  connection->WriteData(result);
}

cmServerProtocol* cmServer::FindMatchingProtocol(
  const std::vector<std::unique_ptr<cmServerProtocol>>& protocols, int major,
  int minor)
{
  cmServerProtocol* bestMatch = nullptr;
  for (const auto& protocol : protocols) {
    auto version = protocol->ProtocolVersion();
    if (major != version.first) {
      continue;
    }
    if (minor == version.second) {
      return protocol.get();
    }
    if (!bestMatch || bestMatch->ProtocolVersion().second < version.second) {
      bestMatch = protocol.get();
    }
  }
  return minor < 0 ? bestMatch : nullptr;
}

void cmServer::WriteProgress(const cmServerRequest& request, int min,
                             int current, int max,
                             const std::string& message) const
{
  assert(min <= current && current <= max);
  assert(message.length() != 0);

  Json::Value obj = Json::objectValue;
  obj[kTYPE_KEY] = kPROGRESS_TYPE;
  obj[kREPLY_TO_KEY] = request.Type;
  obj[kCOOKIE_KEY] = request.Cookie;
  obj[kPROGRESS_MESSAGE_KEY] = message;
  obj[kPROGRESS_MINIMUM_KEY] = min;
  obj[kPROGRESS_MAXIMUM_KEY] = max;
  obj[kPROGRESS_CURRENT_KEY] = current;

  this->WriteJsonObject(request.Connection, obj, nullptr);
}

void cmServer::WriteMessage(const cmServerRequest& request,
                            const std::string& message,
                            const std::string& title) const
{
  if (message.empty()) {
    return;
  }

  Json::Value obj = Json::objectValue;
  obj[kTYPE_KEY] = kMESSAGE_TYPE;
  obj[kREPLY_TO_KEY] = request.Type;
  obj[kCOOKIE_KEY] = request.Cookie;
  obj[kMESSAGE_KEY] = message;
  if (!title.empty()) {
    obj[kTITLE_KEY] = title;
  }

  WriteJsonObject(request.Connection, obj, nullptr);
}

void cmServer::WriteParseError(cmConnection* connection,
                               const std::string& message) const
{
  Json::Value obj = Json::objectValue;
  obj[kTYPE_KEY] = kERROR_TYPE;
  obj[kERROR_MESSAGE_KEY] = message;
  obj[kREPLY_TO_KEY] = "";
  obj[kCOOKIE_KEY] = "";

  this->WriteJsonObject(connection, obj, nullptr);
}

void cmServer::WriteSignal(const std::string& name,
                           const Json::Value& data) const
{
  assert(data.isObject());
  Json::Value obj = data;
  obj[kTYPE_KEY] = kSIGNAL_TYPE;
  obj[kREPLY_TO_KEY] = "";
  obj[kCOOKIE_KEY] = "";
  obj[kNAME_KEY] = name;

  WriteJsonObject(obj, nullptr);
}

void cmServer::WriteResponse(cmConnection* connection,
                             const cmServerResponse& response,
                             const DebugInfo* debug) const
{
  assert(response.IsComplete());

  Json::Value obj = response.Data();
  obj[kCOOKIE_KEY] = response.Cookie;
  obj[kTYPE_KEY] = response.IsError() ? kERROR_TYPE : kREPLY_TYPE;
  obj[kREPLY_TO_KEY] = response.Type;
  if (response.IsError()) {
    obj[kERROR_MESSAGE_KEY] = response.ErrorMessage();
  }

  this->WriteJsonObject(connection, obj, debug);
}

void cmServer::OnConnected(cmConnection* connection)
{
  PrintHello(connection);
}

void cmServer::OnServeStart()
{
  cmServerBase::OnServeStart();
  fileMonitor = std::make_shared<cmFileMonitor>(GetLoop());
}

void cmServer::StartShutDown()
{
  if (fileMonitor) {
    fileMonitor->StopMonitoring();
    fileMonitor.reset();
  }
  cmServerBase::StartShutDown();
}

static void __start_thread(void* arg)
{
  auto server = static_cast<cmServerBase*>(arg);
  std::string error;
  bool success = server->Serve(&error);
  if (!success || !error.empty()) {
    std::cerr << "Error during serve: " << error << std::endl;
  }
}

bool cmServerBase::StartServeThread()
{
  ServeThreadRunning = true;
  uv_thread_create(&ServeThread, __start_thread, this);
  return true;
}

static void __shutdownThread(uv_async_t* arg)
{
  auto server = static_cast<cmServerBase*>(arg->data);
  server->StartShutDown();
}

bool cmServerBase::Serve(std::string* errorMessage)
{
#ifndef NDEBUG
  uv_thread_t blank_thread_t = {};
  assert(uv_thread_equal(&blank_thread_t, &ServeThreadId));
  ServeThreadId = uv_thread_self();
#endif

  errorMessage->clear();

  ShutdownSignal.init(Loop, __shutdownThread, this);

  SIGINTHandler.init(Loop, this);
  SIGHUPHandler.init(Loop, this);

  SIGINTHandler.start(&on_signal, SIGINT);
  SIGHUPHandler.start(&on_signal, SIGHUP);

  OnServeStart();

  {
    cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
    for (auto& connection : Connections) {
      if (!connection->OnServeStart(errorMessage)) {
        return false;
      }
    }
  }

  if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
    // It is important we don't ever let the event loop exit with open handles
    // at best this is a memory leak, but it can also introduce race conditions
    // which can hang the program.
    assert(false && "Event loop stopped in unclean state.");

    *errorMessage = "Internal Error: Event loop stopped in unclean state.";
    return false;
  }

  return true;
}

void cmServerBase::OnConnected(cmConnection*)
{
}

void cmServerBase::OnServeStart()
{
}

void cmServerBase::StartShutDown()
{
  ShutdownSignal.reset();
  SIGINTHandler.reset();
  SIGHUPHandler.reset();

  {
    std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
    for (auto& connection : Connections) {
      connection->OnConnectionShuttingDown();
    }
    Connections.clear();
  }

  uv_walk(&Loop, on_walk_to_shutdown, nullptr);
}

bool cmServerBase::OnSignal(int signum)
{
  (void)signum;
  StartShutDown();
  return true;
}

cmServerBase::cmServerBase(cmConnection* connection)
{
  auto err = uv_loop_init(&Loop);
  (void)err;
  Loop.data = this;
  assert(err == 0);

  AddNewConnection(connection);
}

void cmServerBase::Close()
{
  if (Loop.data) {
    if (ServeThreadRunning) {
      this->ShutdownSignal.send();
      uv_thread_join(&ServeThread);
    }

    uv_loop_close(&Loop);
    Loop.data = nullptr;
  }
}
cmServerBase::~cmServerBase()
{
  Close();
}

void cmServerBase::AddNewConnection(cmConnection* ownedConnection)
{
  {
    std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
    Connections.emplace_back(ownedConnection);
  }
  ownedConnection->SetServer(this);
}

uv_loop_t* cmServerBase::GetLoop()
{
  return &Loop;
}

void cmServerBase::OnDisconnect(cmConnection* pConnection)
{
  auto pred = [pConnection](const std::unique_ptr<cmConnection>& m) {
    return m.get() == pConnection;
  };
  {
    std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
    Connections.erase(
      std::remove_if(Connections.begin(), Connections.end(), pred),
      Connections.end());
  }

  if (Connections.empty()) {
    this->ShutdownSignal.send();
  }
}
