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

#include "cmConfigure.h" // IWYU pragma: keep

#include <memory>
#include <string>
#include <vector>

#include <cm/shared_mutex>

#include <cm3p/json/value.h>
#include <cm3p/uv.h>

#include "cmUVHandlePtr.h"

class cmConnection;
class cmFileMonitor;
class cmServerProtocol;
class cmServerRequest;
class cmServerResponse;

/***
 * This essentially hold and manages a libuv event queue and responds to
 * messages
 * on any of its connections.
 */
class cmServerBase
{
public:
  cmServerBase(cmConnection* connection);
  virtual ~cmServerBase();

  virtual void AddNewConnection(cmConnection* ownedConnection);

  /***
   * The main override responsible for tailoring behavior towards
   * whatever the given server is supposed to do
   *
   * This should almost always be called by the given connections
   * directly.
   *
   * @param connection The connection the request was received on
   * @param request The actual request
   */
  virtual void ProcessRequest(cmConnection* connection,
                              const std::string& request) = 0;
  virtual void OnConnected(cmConnection* connection);

  /***
   * Start a dedicated thread. If this is used to start the server, it will
   * join on the
   * servers dtor.
   */
  virtual bool StartServeThread();
  virtual bool Serve(std::string* errorMessage);

  virtual void OnServeStart();
  virtual void StartShutDown();

  virtual bool OnSignal(int signum);
  uv_loop_t* GetLoop();
  void Close();
  void OnDisconnect(cmConnection* pConnection);

protected:
  mutable cm::shared_mutex ConnectionsMutex;
  std::vector<std::unique_ptr<cmConnection>> Connections;

  bool ServeThreadRunning = false;
  uv_thread_t ServeThread;
  cm::uv_async_ptr ShutdownSignal;
#ifndef NDEBUG
public:
  // When the server starts it will mark down it's current thread ID,
  // which is useful in other contexts to just assert that operations
  // are performed on that same thread.
  uv_thread_t ServeThreadId = {};

protected:
#endif

  uv_loop_t Loop;

  cm::uv_signal_ptr SIGINTHandler;
  cm::uv_signal_ptr SIGHUPHandler;
};

class cmServer : public cmServerBase
{
public:
  class DebugInfo;

  cmServer(cmConnection* conn, bool supportExperimental);
  ~cmServer() override;

  cmServer(cmServer const&) = delete;
  cmServer& operator=(cmServer const&) = delete;

  bool Serve(std::string* errorMessage) override;

  cmFileMonitor* FileMonitor() const;

private:
  void RegisterProtocol(std::unique_ptr<cmServerProtocol> protocol);

  // Callbacks from cmServerConnection:

  void ProcessRequest(cmConnection* connection,
                      const std::string& request) override;
  std::shared_ptr<cmFileMonitor> fileMonitor;

public:
  void OnServeStart() override;

  void StartShutDown() override;

public:
  void OnConnected(cmConnection* connection) override;

private:
  static void reportProgress(const std::string& msg, float progress,
                             const cmServerRequest& request);
  static void reportMessage(const std::string& msg, const char* title,
                            const cmServerRequest& request);

  // Handle requests:
  cmServerResponse SetProtocolVersion(const cmServerRequest& request);

  void PrintHello(cmConnection* connection) const;

  // Write responses:
  void WriteProgress(const cmServerRequest& request, int min, int current,
                     int max, const std::string& message) const;
  void WriteMessage(const cmServerRequest& request, const std::string& message,
                    const std::string& title) const;
  void WriteResponse(cmConnection* connection,
                     const cmServerResponse& response,
                     const DebugInfo* debug) const;
  void WriteParseError(cmConnection* connection,
                       const std::string& message) const;
  void WriteSignal(const std::string& name, const Json::Value& obj) const;

  void WriteJsonObject(Json::Value const& jsonValue,
                       const DebugInfo* debug) const;

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

  static cmServerProtocol* FindMatchingProtocol(
    const std::vector<std::unique_ptr<cmServerProtocol>>& protocols, int major,
    int minor);

  const bool SupportExperimental;

  cmServerProtocol* Protocol = nullptr;
  std::vector<std::unique_ptr<cmServerProtocol>> SupportedProtocols;

  friend class cmServerProtocol;
  friend class cmServerRequest;
};
