#pragma once

#include <api/project.h>
#include <api/requirement.h>
#include <dBus/dBus.h>
#include <memory>
#include <thread>

namespace core::project
{
class RequirementManager;
//--------------------------------------------------------------
class ProjectManager : public dBus::Node
{
  using RequirementManagerPtr = std::shared_ptr<RequirementManager>;

  public:
  ProjectManager() = delete;                                             // Default constructor
  virtual ~ProjectManager();                                             // Default destructor
  ProjectManager(const ProjectManager &obj)                = delete;     // Copy constructor
  ProjectManager(ProjectManager &&obj) noexcept            = delete;     // Move constructor
  ProjectManager &operator=(const ProjectManager &obj)     = delete;     // Copy assignment operator
  ProjectManager &operator=(ProjectManager &&obj) noexcept = delete;     // Move assignment operator

  explicit ProjectManager(dBus::Bus &bus);     // Constructor

  protected:
  std::filesystem::path m_filePath;     // Path of the currently opened project file

  RequirementManagerPtr m_requirementManager;     // Pointer to the requirement manager of the current project

  private:
  void openFile(const std::filesystem::path &filePath);          // Open a project file and load the requirements
  void saveFile(const std::filesystem::path &filePath = "");     // Save the current requirements to a project file

  // dBus management
  using Message_ptr = std::shared_ptr<dBus::Message>;
  void         runBusListener();                                  // Run the bus listener thread
  void         stopBusListener();                                 // Stop the bus listener thread
  void         processMessageBus(const Message_ptr &message);     // Process a message received from the bus
  std::jthread m_busListenerThread;                               // Thread for listening to bus messages related to requirements

  // Events processing
  void on_projectOperationEvent(const Message_ptr &message);                                           // Process a file operation event
  void on_projectCreateFileEvent(const api::project::ProjectOperationMessage_ptr &message);            // Process a file creation event
  void on_projectOpenFileEvent(const api::project::ProjectOperationMessage_ptr &message);              // Process a file opening event
  void on_projectSaveFileEvent(const api::project::ProjectOperationMessage_ptr &message);              // Process a file saving event
  void on_projectCloseFileEvent(const api::project::ProjectOperationMessage_ptr &message);             // Process a file closing event
  void on_requirementGetEvent(const api::requirement::GetRequirementMessage_ptr &message) const;       // Process a requirement get event
  void on_requirementGetChildrenEvent(const api::requirement::GetChildrenRequirementMessage_ptr &message) const; // Process a requirement get children event
  void on_requirementAddEvent(const api::requirement::AddRequirementMessage_ptr &message) const;       // Process a requirement addition event
  void on_requirementUpdateEvent(const api::requirement::UpdateRequirementMessage_ptr &message) const; // Process a requirement update event
  void on_requirementDeleteEvent(const api::requirement::DeleteRequirementMessage_ptr &message) const; // Process a requirement deletion event
};
//--------------------------------------------------------------
}     // namespace core::project
