#pragma once
#include <SDL2/SDL.h>
#include <memory>
#include <string>

namespace quokka_gfx
{
class Screen;
class AssetManager;
class InputManager;
class RendererManager;
class ScreenManager;
//------------------------------------------------------------
class Application
{
  friend class RendererManager;
  friend class Screen;

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

  explicit Application(const std::string &title);     // Constructor

  void initScreen(std::unique_ptr<Screen> screen) const;     // Initialize the first screen

  void run();      // Main loop
  void quit();     // Quit the application

  // Accessors for subsystems
  [[nodiscard]] AssetManager    *assetManager() const;
  [[nodiscard]] InputManager    *inputManager() const;
  [[nodiscard]] RendererManager *rendererManager() const;
  [[nodiscard]] ScreenManager   *screenManager() const;

  protected:
  SDL_Window   *m_window      = nullptr;
  SDL_Renderer *m_sdlRenderer = nullptr;

  bool m_running = false;     // Main loop flag

  // Subsystems
  std::unique_ptr<AssetManager>    m_assetManager;        // Asset manager
  std::unique_ptr<InputManager>    m_inputManager;        // Input manager
  std::unique_ptr<RendererManager> m_rendererManager;     // Renderer manager
  std::unique_ptr<ScreenManager>   m_screenManager;       // Screen manager

  private:
  void init(const std::string &title);     // Initialisation
  void handleEvents();                     // Handle SDL events
  void update(double deltaTime) const;     // Update game state
  void render() const;                     // Render the game
  void cleanup() const;                    // Cleanup resources
};
//------------------------------------------------------------
}     // namespace quokka_gfx
