#ifndef XCB_XORG_API_H
#define XCB_XORG_API_H

#include <string>
#include <vector>
#include <memory>
#include <atomic>
#include <map>
#include <xcb/xcb.h>

namespace xcb_xorg {

/**
 * @brief Connection identifier for X server connections
 */
struct ConnectionIdentifier
{
    int display;
    int screen;

    bool operator<(const ConnectionIdentifier& other) const
    {
        if (display != other.display) return display < other.display;
        return screen < other.screen;
    }

    std::string stringify() const;
};

/**
 * @brief Represents a single X server connection using XCB
 *
 * This class manages a single connection to the X server. It provides
 * RAII management for the connection and maintains a reference count
 * for shared usage.
 */
class XcbConnection
{
public:
    /**
     * @brief Constructor for creating a new connection
     * @param id Connection identifier specifying display and screen
     * @throws std::runtime_error if connection fails
     */
    explicit XcbConnection(const ConnectionIdentifier& id);

    // Delete copy/move operations - we'll manage instances through pointers
    XcbConnection(const XcbConnection&) = delete;
    XcbConnection& operator=(const XcbConnection&) = delete;
    XcbConnection(XcbConnection&&) = delete;
    XcbConnection& operator=(XcbConnection&&) = delete;

    /**
     * @brief Destructor - automatically closes the connection
     */
    ~XcbConnection() = default;

    /**
     * @brief Get the underlying XCB connection
     * @return Raw XCB connection pointer
     */
    xcb_connection_t* getConnection() const { return connection.get(); }

    /**
     * @brief Get the connection identifier
     * @return Connection identifier
     */
    const ConnectionIdentifier& getIdentifier() const { return connectionIdentifier; }

    /**
     * @brief Increment reference count
     */
    void incrementRefCount() { refCount++; }

    /**
     * @brief Decrement reference count
     * @return New reference count
     */
    int decrementRefCount() { return --refCount; }

    /**
     * @brief Get current reference count
     * @return Current reference count
     */
    int getRefCount() const { return refCount; }

    /**
     * @brief Check if connection is valid
     * @return true if connection is valid, false otherwise
     */
    bool isValid() const { return connection && !xcb_connection_has_error(connection.get()); }

private:
    std::unique_ptr<xcb_connection_t, decltype(&xcb_disconnect)> connection;
    ConnectionIdentifier connectionIdentifier;
    std::atomic<int> refCount;
};

/**
 * @brief Manages multiple X server connections
 *
 * This class manages a collection of XcbConnection instances. It ensures
 * that each unique display and screen combination has a single connection,
 * and provides RAII management for these connections.
 */
class ConnectionManager
{
public:
    /**
     * @brief Get or create a connection to the X server
     * @param id Connection identifier specifying display and screen
     * @return Shared pointer to the connection
     * @throws std::runtime_error if connection fails
     */
    static std::shared_ptr<XcbConnection> getOrCreateConnection(
        const ConnectionIdentifier& id);

    /**
     * @brief Clean up all connections
     */
    static void cleanupAllConnections();

    /**
     * @brief Get the number of active connections
     * @return Number of active connections
     */
    static size_t getConnectionCount();

    /**
     * @brief Remove a specific connection from the manager
     * @param id Connection identifier to remove
     */
    static void removeConnection(const ConnectionIdentifier& id);

private:
    static std::map<ConnectionIdentifier, std::shared_ptr<XcbConnection>> connections;
};

/**
 * @brief Window search functionality
 */
namespace window_search {

enum class MatchType { SUBSTRING, EXACT, ID };

/**
 * @brief Find window by ID
 * @param conn XCB connection
 * @param root Root window
 * @param targetId Target window ID
 * @return Window ID if found, 0 if not found
 */
xcb_window_t findById(xcb_connection_t* conn, xcb_window_t root, uint32_t targetId);

/**
 * @brief Find window by name
 * @param conn XCB connection
 * @param root Root window
 * @param targetName Target window name
 * @param outWindowName Output parameter for actual window name
 * @param matchType Type of name matching to perform
 * @return Window ID if found, 0 if not found
 */
xcb_window_t findByName(xcb_connection_t* conn, xcb_window_t root,
    const std::string& targetName, std::string& outWindowName,
    MatchType matchType);

} // namespace window_search

} // namespace xcb_xorg

// Function signature types for dynamic loading of libxcbXorg
typedef std::shared_ptr<xcb_xorg::XcbConnection> get_or_create_connection_fn(
    int display, int screen);
typedef void cleanup_connections_fn();
typedef void dereference_connection_fn(
    std::shared_ptr<xcb_xorg::XcbConnection> conn);
typedef xcb_window_t find_window_by_id_fn(
    void* conn, xcb_window_t root, uint32_t targetId);
typedef xcb_window_t find_window_by_name_fn(void* conn, xcb_window_t root,
    const std::string& targetName, std::string& outWindowName,
    xcb_xorg::window_search::MatchType matchType);

#endif // XCB_XORG_API_H
