#pragma once

#include <memory>
#include <functional>
#include <vector>
#include <string>
#include <map>
#include <cstdint>

#ifdef __linux__
#include <spa/utils/hook.h>
#include <spa/pod/pod.h>
#endif

// Forward declarations for Pipewire/sdbus to avoid header pollution
struct pw_thread_loop;
struct pw_stream;
struct pw_context;

namespace sdbus {
    class IConnection;
    class IProxy;
    class Variant;
}

namespace scar {

class VideoEncoder;  // Forward declaration

enum class ScreenCaptureBackend {
    FFMPEG_X11,           // X11 via ffmpeg
    FFMPEG_WAYLAND,       // Wayland via ffmpeg + portal
    FFMPEG_WINDOWS,       // Windows GDI via ffmpeg
    PORTAL_PIPEWIRE       // xdg-desktop-portal + Pipewire (Wayland/Hyprland)
};

// Screen capture supporting multiple backends
class ScreenCapture {
public:
    ScreenCapture();
    ~ScreenCapture();
    
    // Auto-detect and start screen capture
    bool start();
    
    // Start with specific backend
    bool start(ScreenCaptureBackend backend);
    
    // Stop capturing
    void stop();
    
    // Check if currently capturing
    bool isCapturing() const { return capturing_; }
    
    // Set frame callback
    using FrameCallback = std::function<void(const std::vector<uint8_t>& frameData, int width, int height)>;
    void setFrameCallback(FrameCallback callback);

private:
    ScreenCaptureBackend detectBestBackend();
    
    bool startX11Capture();
    bool startWaylandCapture();
    bool startWindowsCapture();
    bool startPortalCapture();
    
    // sdbus Portal methods
    bool initPortalConnection();
    void cleanupPortalConnection();
    std::string createPortalSession();
    bool selectPortalSources(const std::string& session_handle);
    bool startPortalSession(const std::string& session_handle, uint32_t& node_id);
    int openPipeWireRemote(const std::string& session_handle);
    uint32_t getStreamsNodeId(const std::string& session_handle);
    
    // Portal async response handlers
    void onCreateSessionResponse(uint32_t response, const std::map<std::string, sdbus::Variant>& results);
    void onSelectSourcesResponse(uint32_t response, const std::map<std::string, sdbus::Variant>& results);
    void onStartSessionResponse(uint32_t response, const std::map<std::string, sdbus::Variant>& results);
    void setupResponseSignal(const std::string& request_handle, 
                            std::function<void(uint32_t, const std::map<std::string, sdbus::Variant>&)> callback);
    
    // Pipewire methods
    bool initPipewire(int fd, uint32_t node_id);
    void cleanupPipewire();
    static void onStreamProcess(void* userdata);
    static void onStreamParamChanged(void* userdata, uint32_t id, const struct spa_pod* param);
    
    bool capturing_;
    ScreenCaptureBackend backend_;
    FrameCallback frameCallback_;
    
    // sdbus members
    std::shared_ptr<sdbus::IConnection> portal_connection_;
    std::unique_ptr<sdbus::IProxy> screencast_proxy_;
    std::vector<std::unique_ptr<sdbus::IProxy>> request_proxies_;  // Keep request proxies alive for signal handlers
    std::string session_path_;
    std::string pending_request_path_;
    bool portal_session_ready_;
    bool portal_sources_selected_;
    bool portal_started_;
    
    // Pipewire members
    pw_thread_loop* pw_loop_;
    pw_stream* pw_stream_;
    pw_context* pw_context_;
    spa_hook stream_listener_;
    
    int frame_width_;
    int frame_height_;
    
    // Video encoder
    std::unique_ptr<VideoEncoder> encoder_;
};

} // namespace scar
