/*
 * Copyright © 2017-2019 Canonical Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
 */

#include "in_process_server.h"
#include "thread_proxy.h"
#include "version_specifier.h"
#include "wlcs/display_server.h"
#include "helpers.h"
#include "wlcs/pointer.h"
#include "wlcs/touch.h"
#include "xdg_shell_v6.h"
#include "xdg_shell_stable.h"
#include "generated/wayland-client.h"
#include "generated/xdg-shell-unstable-v6-client.h"
#include "generated/xdg-shell-client.h"

#include "linux/input.h"
#include <boost/throw_exception.hpp>
#include <stdexcept>
#include <memory>
#include <vector>
#include <algorithm>
#include <optional>
#include <map>
#include <unordered_map>
#include <chrono>
#include <poll.h>

using namespace std::literals::chrono_literals;

class ShimNotImplemented : public std::logic_error
{
public:
    ShimNotImplemented() : std::logic_error("Function not implemented in display server shim")
    {
    }

    ShimNotImplemented(const std::string& name)
        : std::logic_error("Function '" + name + "()' not implemented in display server shim")
    {
    }
};

namespace
{
auto interface_description_if_valid(wl_interface const* interface) -> std::string
{
    if (interface)
    {
        using namespace std::literals::string_literals;
        return interface->name + " v"s + std::to_string(interface->version);
    }
    return "<UNKNOWN INTERFACE>";
}
}
wlcs::ProtocolError::ProtocolError(wl_interface const* interface, uint32_t code)
    : std::system_error(EPROTO, std::system_category(), "Wayland protocol error"),
      interface_{interface},
      code_{code},
      message{
          std::string{"Wayland protocol error: "} +
          std::to_string(code) +
          " on interface " + interface_description_if_valid(interface)}
    {
    }

char const* wlcs::ProtocolError::what() const noexcept
{
    return message.c_str();
}

uint32_t wlcs::ProtocolError::error_code() const
{
    return code_;
}

wl_interface const* wlcs::ProtocolError::interface() const
{
    return interface_;
}

wlcs::ExtensionExpectedlyNotSupported::ExtensionExpectedlyNotSupported(char const* extension, VersionSpecifier const& version)
    : std::runtime_error{
        std::string{"Extension: "} +
        extension + " version " + version.describe() +
        " not supported by compositor under test."}
{
    auto const skip_reason =
        std::string{"Missing extension: "} + extension + version.describe();
    ::testing::Test::RecordProperty("wlcs-skip-test", skip_reason);
}

wlcs::Timeout::Timeout(char const* message)
    : std::runtime_error(message)
{
}

class wlcs::Pointer::Impl
{
public:
    template<typename Proxy>
    Impl(
        WlcsPointer* raw_device,
        std::shared_ptr<Proxy> const& proxy,
        std::shared_ptr<void const> const& keep_dso_loaded)
        : keep_dso_loaded{keep_dso_loaded},
          pointer{raw_device}
    {
        setup_thunks(proxy);
    }

    ~Impl()
    {
        destroy_thunk();
    }

    void move_to(int x, int y)
    {
        move_absolute_thunk(wl_fixed_from_int(x), wl_fixed_from_int(y));
    }

    void move_by(int dx, int dy)
    {
        move_relative_thunk(wl_fixed_from_int(dx), wl_fixed_from_int(dy));
    }

    void button_down(int button)
    {
        button_down_thunk(button);
    }

    void button_up(int button)
    {
        button_up_thunk(button);
    }

private:
    template<typename Proxy>
    void setup_thunks(std::shared_ptr<Proxy> const& proxy)
    {
        move_absolute_thunk = proxy->register_op(
            [this](wl_fixed_t x, wl_fixed_t y)
            {
                pointer->move_absolute(pointer, x, y);
            });
        move_relative_thunk = proxy->register_op(
            [this](wl_fixed_t dx, wl_fixed_t dy)
            {
                pointer->move_relative(pointer, dx, dy);
            });
        button_down_thunk = proxy->register_op(
            [this](int button)
            {
                pointer->button_down(pointer, button);
            });
        button_up_thunk = proxy->register_op(
            [this](int button)
            {
                pointer->button_up(pointer, button);
            });
        destroy_thunk = proxy->register_op(
            [this]()
            {
                pointer->destroy(pointer);
            });
    }

    std::shared_ptr<void const> const keep_dso_loaded;
    WlcsPointer* const pointer;

    std::function<void(wl_fixed_t, wl_fixed_t)> move_absolute_thunk;
    std::function<void(wl_fixed_t, wl_fixed_t)> move_relative_thunk;
    std::function<void(int)> button_down_thunk;
    std::function<void(int)> button_up_thunk;
    std::function<void()> destroy_thunk;
};

wlcs::Pointer::~Pointer() = default;
wlcs::Pointer::Pointer(Pointer&&) = default;

template<typename Proxy>
wlcs::Pointer::Pointer(
    WlcsPointer* raw_device,
    std::shared_ptr<Proxy> const& proxy,
    std::shared_ptr<void const> const& keep_dso_loaded)
    : impl{std::make_unique<Impl>(raw_device, proxy, keep_dso_loaded)}
{
}

void wlcs::Pointer::move_to(int x, int y)
{
    impl->move_to(x, y);
}

void wlcs::Pointer::move_by(int dx, int dy)
{
    impl->move_by(dx, dy);
}

void wlcs::Pointer::button_down(int button)
{
    impl->button_down(button);
}

void wlcs::Pointer::button_up(int button)
{
    impl->button_up(button);
}

void wlcs::Pointer::click(int button)
{
    button_down(button);
    button_up(button);
}

void wlcs::Pointer::left_button_down()
{
    button_down(BTN_LEFT);
}

void wlcs::Pointer::left_button_up()
{
    button_up(BTN_LEFT);
}

void wlcs::Pointer::left_click()
{
    click(BTN_LEFT);
}

class wlcs::Touch::Impl
{
public:
    template<typename Proxy>
    Impl(
        WlcsTouch* raw_device,
        std::shared_ptr<Proxy> const& proxy,
        std::shared_ptr<void const> const& keep_dso_loaded)
        : keep_dso_loaded{keep_dso_loaded},
          touch{raw_device, proxy->register_op([](WlcsTouch* raw_device) { raw_device->destroy(raw_device); })}
    {
        if (touch->version != WLCS_TOUCH_VERSION)
        {
            BOOST_THROW_EXCEPTION((
                std::runtime_error{
                    std::string{"Unexpected WlcsTouch version. Expected: "} +
                    std::to_string(WLCS_TOUCH_VERSION) +
                    " received: " +
                    std::to_string(touch->version)}));
        }
        set_up_thunks(proxy);
    }

    void down_at(int x, int y)
    {
        touch->touch_down(touch.get(), x, y);
    }

    void move_to(int x, int y)
    {
        touch->touch_move(touch.get(), x, y);
    }

    void up()
    {
        touch->touch_up(touch.get());
    }

private:
    template<typename Proxy>
    void set_up_thunks(std::shared_ptr<Proxy> const& proxy)
    {
        touch_down_thunk = proxy->register_op(
            [this](int x, int y)
            {
                touch->touch_down(touch.get(), x, y);
            });
        touch_move_thunk = proxy->register_op(
            [this](int x, int y)
            {
                touch->touch_move(touch.get(), x, y);
            });
        touch_up_thunk = proxy->register_op(
            [this]()
            {
                touch->touch_up(touch.get());
            });
    }

    std::shared_ptr<void const> const keep_dso_loaded;
    std::unique_ptr<WlcsTouch, std::function<void(WlcsTouch*)>> const touch;

    std::function<void(int, int)> touch_down_thunk;
    std::function<void(int, int)> touch_move_thunk;
    std::function<void()> touch_up_thunk;
};

wlcs::Touch::~Touch() = default;
wlcs::Touch::Touch(Touch&&) = default;

template<typename Proxy>
wlcs::Touch::Touch(
    WlcsTouch* raw_device,
    std::shared_ptr<Proxy> const& proxy,
    std::shared_ptr<void const> const& keep_dso_loaded)
    : impl{std::make_unique<Impl>(raw_device, proxy, keep_dso_loaded)}
{
}

void wlcs::Touch::down_at(int x, int y)
{
    impl->down_at(x, y);
}

void wlcs::Touch::move_to(int x, int y)
{
    impl->move_to(x, y);
}

void wlcs::Touch::up()
{
    impl->up();
}

namespace
{
std::shared_ptr<std::unordered_map<std::string, uint32_t> const> extract_supported_extensions(WlcsDisplayServer* server)
{
    if (server->version < 2)
    {
        return {};
    }

    auto const descriptor = server->get_descriptor(server);
    auto extensions = std::make_shared<std::unordered_map<std::string, uint32_t>>();

    for (auto i = 0u; i < descriptor->num_extensions; ++i)
    {
        (*extensions)[descriptor->supported_extensions[i].name] = descriptor->supported_extensions[i].version;
    }
    return extensions;
}

class NullProxy
{
public:
    template<typename Callable>
    auto register_op(Callable handler)
    {
        return handler;
    }
};
}

class wlcs::Server::Impl
{
public:
    Impl(std::shared_ptr<WlcsServerIntegration const> const& hooks, int argc, char const** argv)
        : server{hooks->create_server(argc, argv), hooks->destroy_server},
          thread_context{make_context_if_needed(*server)},
          hooks{hooks},
          supported_extensions_{extract_supported_extensions(server.get())}
    {
        if (hooks->version < 1)
        {
            BOOST_THROW_EXCEPTION((std::runtime_error{"Server integration too old"}));
        }
        if (server->version < 1)
        {
            BOOST_THROW_EXCEPTION((std::runtime_error{"Server integration too old"}));
        }
        if (!server->stop)
        {
            BOOST_THROW_EXCEPTION((std::logic_error{"Missing required WlcsDisplayServer.stop definition"}));
        }
        if (thread_context)
        {
            initialise_thunks(thread_context->proxy);
        }
        else
        {
            initialise_thunks(std::make_shared<NullProxy>());
        }
    }

    void start()
    {
        if (thread_context)
        {
            thread_context->server_thread = std::thread{
                [this]()
                {
                    server->start_on_this_thread(server.get(), thread_context->event_loop.get());
                }};
        }
        else
        {
            server->start(server.get());
        }
    }

    void stop()
    {
        stop_thunk();
    }

    int create_client_socket()
    {
        auto fd = create_client_socket_thunk();
        if (fd < 0)
        {
            BOOST_THROW_EXCEPTION((std::system_error{
                errno,
                std::system_category(),
                "Failed to get client socket from server"}));
        }
        return fd;
    }

    Pointer create_pointer()
    {
        if (thread_context)
        {
            return Pointer{create_pointer_thunk(), thread_context->proxy, hooks};
        }
        else
        {
            return Pointer{create_pointer_thunk(), std::make_shared<NullProxy>(), hooks};
        }
    }

    Touch create_touch()
    {
        if (thread_context)
        {
            return Touch{create_touch_thunk(), thread_context->proxy, hooks};
        }
        else
        {
            return Touch{create_touch_thunk(), std::make_shared<NullProxy>(), hooks};
        }
    }

    void move_surface_to(Surface& surface, int x, int y)
    {
        // Ensure the server knows about the IDs we're about to send...
        surface.owner().roundtrip();

        position_window_absolute_thunk(surface.owner(), surface, x, y);
    }

    WlcsDisplayServer* wlcs_server() const
    {
        return server.get();
    }

    std::shared_ptr<const std::unordered_map<std::string, uint32_t>> supported_extensions() const
    {
        return supported_extensions_;
    }

private:
    struct ThreadContext
    {
        explicit ThreadContext(std::unique_ptr<struct wl_event_loop, decltype(&wl_event_loop_destroy)> loop)
            : event_loop{std::move(loop)},
              proxy{std::make_shared<ThreadProxy>(event_loop.get())}
        {
        }
        ThreadContext(ThreadContext&&) = default;

        ~ThreadContext()
        {
            if (server_thread.joinable())
            {
                server_thread.join();
            }
        }

        std::unique_ptr<struct wl_event_loop, void(*)(struct wl_event_loop*)> event_loop;
        std::thread server_thread;
        std::shared_ptr<ThreadProxy> proxy;
    };

    static std::optional<ThreadContext> make_context_if_needed(WlcsDisplayServer const& server)
    {
        if (server.version >= 3)
        {
            if (!server.start)
            {
                if (!server.start_on_this_thread)
                {
                    BOOST_THROW_EXCEPTION((
                        std::runtime_error{"Server integration missing both start() and start_on_this_thread()"}));
                }
                auto loop = std::unique_ptr<struct wl_event_loop, decltype(&wl_event_loop_destroy)>{
                    wl_event_loop_create(),
                    &wl_event_loop_destroy
                };
                if (!loop)
                {
                    BOOST_THROW_EXCEPTION((
                        std::runtime_error{"Failed to create eventloop for WLCS events"}));
                }

                return {ThreadContext{std::move(loop)}};
            }
        }
        return {};
    };

    std::unique_ptr<WlcsDisplayServer, void(*)(WlcsDisplayServer*)> const server;
    std::optional<ThreadContext> thread_context;
    std::shared_ptr<WlcsServerIntegration const> const hooks;
    std::shared_ptr<std::unordered_map<std::string, uint32_t> const> const supported_extensions_;

    template<typename Proxy>
    void initialise_thunks(std::shared_ptr<Proxy> proxy)
    {
        stop_thunk = proxy->register_op(
            [this]()
            {
                server->stop(server.get());
            });
        create_client_socket_thunk = proxy->register_op(
            [this]()
            {
                return server->create_client_socket(server.get());
            });
        create_pointer_thunk = proxy->register_op(
            [this]()
            {
                return server->create_pointer(server.get());
            });
        create_touch_thunk = proxy->register_op(
            [this]()
            {
                return server->create_touch(server.get());
            });
        position_window_absolute_thunk = proxy->register_op(
            [this](
                struct wl_display* client,
                struct wl_surface* surface,
                int x,
                int y)
            {
                server->position_window_absolute(
                    server.get(),
                    client,
                    surface,
                    x,
                    y);
            });
    }
    std::function<void()> stop_thunk;
    std::function<int()> create_client_socket_thunk;
    std::function<WlcsPointer*()> create_pointer_thunk;
    std::function<WlcsTouch*()> create_touch_thunk;
    std::function<void(struct wl_display*, struct wl_surface*, int, int)> position_window_absolute_thunk;
};

wlcs::Server::Server(
    std::shared_ptr<WlcsServerIntegration const> const& hooks,
    int argc,
    char const** argv)
    : impl{std::make_unique<wlcs::Server::Impl>(hooks, argc, argv)}
{
}

wlcs::Server::~Server() = default;

void wlcs::Server::start()
{
    impl->start();
}

void wlcs::Server::stop()
{
    impl->stop();
}

std::shared_ptr<const std::unordered_map<std::string, uint32_t>> wlcs::Server::supported_extensions()
{
    return impl->supported_extensions();
}

int wlcs::Server::create_client_socket()
{
    return impl->create_client_socket();
}

void wlcs::Server::move_surface_to(Surface& surface, int x, int y)
{
    impl->move_surface_to(surface, x, y);
}

wlcs::Pointer wlcs::Server::create_pointer()
{
    return impl->create_pointer();
}

wlcs::Touch wlcs::Server::create_touch()
{
    return impl->create_touch();
}

wlcs::InProcessServer::InProcessServer()
    : server{helpers::get_test_hooks(), helpers::get_argc(), helpers::get_argv()}
{
}

void wlcs::InProcessServer::SetUp()
{
    server.start();
}

void wlcs::InProcessServer::TearDown()
{
    server.stop();
}

wlcs::Server& wlcs::InProcessServer::the_server()
{
    return server;
}

void throw_wayland_error(wl_display* display)
{
    auto err = wl_display_get_error(display);
    if (err != EPROTO)
    {
        BOOST_THROW_EXCEPTION((std::system_error{
            err,
            std::system_category(),
            "Error while dispatching Wayland events"
        }));
    }
    else
    {
        uint32_t object_id;
        uint32_t protocol_error;
        wl_interface const* interface;
        protocol_error = wl_display_get_protocol_error(display, &interface, &object_id);
        BOOST_THROW_EXCEPTION((wlcs::ProtocolError{interface, protocol_error}));
    }
}

class wlcs::Client::Impl
{
public:
    Impl(Server& server)
        : supported_extensions{server.supported_extensions()}
    {
        try
        {
            display = wl_display_connect_to_fd(server.create_client_socket());
        }
        catch (ShimNotImplemented const&)
        {
            // TODO: Warn about connecting to who-knows-what
            display = wl_display_connect(NULL);
        }

        if (!display)
        {
            BOOST_THROW_EXCEPTION((std::runtime_error{"Failed to connect to Wayland socket"}));
        }

        registry = wl_display_get_registry(display);
        wl_registry_add_listener(registry, &registry_listener, this);

        server_roundtrip();
    }

    ~Impl()
    {
        if (shm) wl_shm_destroy(shm);
        if (shell) wl_shell_destroy(shell);
        if (compositor) wl_compositor_destroy(compositor);
        if (subcompositor) wl_subcompositor_destroy(subcompositor);
        if (registry) wl_registry_destroy(registry);
        if (seat) wl_seat_destroy(seat);
        if (keyboard) wl_keyboard_destroy(keyboard);
        if (pointer) wl_pointer_destroy(pointer);
        if (touch) wl_touch_destroy(touch);
        if (xdg_shell_v6) zxdg_shell_v6_destroy(xdg_shell_v6);
        if (xdg_shell_stable) xdg_wm_base_destroy(xdg_shell_stable);
        for (auto const& output: outputs)
            wl_output_destroy(output->current.output);
        for (auto const& callback: destruction_callbacks)
            callback();
        destruction_callbacks.clear();
        wl_display_disconnect(display);
    }

    struct wl_display* wl_display() const
    {
        return display;
    }

    struct wl_compositor* wl_compositor() const
    {
        return compositor;
    }

    struct wl_subcompositor* wl_subcompositor() const
    {
        return subcompositor;
    }

    struct wl_shm* wl_shm() const
    {
        return shm;
    }

    struct wl_seat* wl_seat() const
    {
        return seat;
    }

    void run_on_destruction(std::function<void()> callback)
    {
        destruction_callbacks.push_back(callback);
    }

    ShmBuffer const& create_buffer(Client& client, int width, int height)
    {
        auto buffer = std::make_shared<ShmBuffer>(client, width, height);
        run_on_destruction([buffer]() mutable
            {
                buffer.reset();
            });
        return *buffer;
    }

    Surface create_wl_shell_surface(Client& client, int width, int height)
    {
        Surface surface{client};

        wl_shell_surface * shell_surface = wl_shell_get_shell_surface(the_shell(), surface);
        surface.run_on_destruction([shell_surface]()
            {
                wl_shell_surface_destroy(shell_surface);
            });
        wl_shell_surface_set_toplevel(shell_surface);

        wl_surface_commit(surface);

        surface.attach_visible_buffer(width, height);

        return surface;
    }

    Surface create_xdg_shell_v6_surface(Client& client, int width, int height)
    {
        Surface surface{client};

        auto xdg_surface = std::make_shared<XdgSurfaceV6>(client, surface);
        auto xdg_toplevel = std::make_shared<XdgToplevelV6>(*xdg_surface);

        surface.run_on_destruction([xdg_surface, xdg_toplevel]() mutable
            {
                xdg_toplevel.reset();
                xdg_surface.reset();
            });

        wl_surface_commit(surface);

        surface.attach_visible_buffer(width, height);

        return surface;
    }

    Surface create_xdg_shell_stable_surface(Client& client, int width, int height)
    {
        Surface surface{client};

        auto xdg_surface = std::make_shared<XdgSurfaceStable>(client, surface);
        auto xdg_toplevel = std::make_shared<XdgToplevelStable>(*xdg_surface);

        // Protocol *requires* us to ack the initial configure before attaching a buffer
        bool initial_configure_received = false;
        EXPECT_CALL(*xdg_surface, configure(testing::_))
            .WillOnce(
                [&initial_configure_received, xdg_surface = static_cast<struct xdg_surface*>(*xdg_surface)](uint32_t serial)
                {
                    xdg_surface_ack_configure(xdg_surface, serial);
                    initial_configure_received = true;
                });

        surface.run_on_destruction([xdg_surface, xdg_toplevel]() mutable
            {
                xdg_toplevel.reset();
                xdg_surface.reset();
            });

        wl_surface_commit(surface);

        client.dispatch_until([&initial_configure_received]() { return initial_configure_received; });
        /* Make absolutely sure the functor above, which captures a stack variable by reference
         * is not going to be invoked outside this function
         */
        testing::Mock::VerifyAndClearExpectations(xdg_surface.get());

        /* And we might as well ack any subsequent configures.
         * Since we don't need to capture anything but the xdg_surface, which has to be
         * live if we're getting a callback on it, this is safe to escape this frame
         */
        ON_CALL(*xdg_surface, configure(testing::_))
            .WillByDefault(
                [xdg_surface = static_cast<struct xdg_surface*>(*xdg_surface)](uint32_t serial)
                {
                    xdg_surface_ack_configure(xdg_surface, serial);
                });

        surface.attach_visible_buffer(width, height);

        return surface;
    }

    Surface create_visible_surface(Client& client, int width, int height)
    {
        if (shell)
        {
            return create_wl_shell_surface(client, width, height);
        }
        else if (xdg_shell_stable)
        {
            return create_xdg_shell_stable_surface(client, width, height);
        }
        else if (xdg_shell_v6)
        {
            return create_xdg_shell_v6_surface(client, width, height);
        }
        else
        {
            throw std::runtime_error("compositor does not support any known shell protocols");
        }
    }

    wl_shell* the_shell() const
    {
        if (shell)
        {
            return shell;
        }
        else
        {
            if (!supported_extensions || !supported_extensions->count("wl_shell"))
            {
                BOOST_THROW_EXCEPTION((ExtensionExpectedlyNotSupported{"wl_shell", AnyVersion}));
            }
            else
            {
                throw std::runtime_error("Failed to bind to wl_shell");
            }
        }
    }

    zxdg_shell_v6* the_xdg_shell_v6() const
    {
        if (xdg_shell_v6)
        {
            return xdg_shell_v6;
        }
        else
        {
            if (!supported_extensions || !supported_extensions->count("zxdg_shell_v6"))
            {
                BOOST_THROW_EXCEPTION((ExtensionExpectedlyNotSupported{"zxdg_shell_v6", AnyVersion}));
            }
            else
            {
                throw std::runtime_error("Failed to bind to zxdg_shell_v6");
            }
        }
    }

    xdg_wm_base* the_xdg_shell_stable() const
    {
        return xdg_shell_stable;
    }

    wl_pointer* the_pointer() const { return pointer; }

    wl_surface* keyboard_focused_window() const
    {
        return keyboard_focused_surface;
    }

    wl_surface* window_under_cursor() const
    {
        if (current_pointer_location)
        {
            return current_pointer_location->surface;
        }
        return nullptr;
    }

    wl_surface* touched_window() const
    {
        wl_surface* surface = nullptr;
        for (auto const& touch : current_touches)
        {
            if (surface && touch.second.surface != surface)
                BOOST_THROW_EXCEPTION(std::runtime_error("Multiple surfaces have active touches"));
            else
                surface = touch.second.surface;
        }
        return surface;
    }

    std::pair<wl_fixed_t, wl_fixed_t> pointer_position() const
    {
        return current_pointer_location.value().coordinates;
    };

    std::pair<wl_fixed_t, wl_fixed_t> touch_position() const
    {
        if (current_touches.empty())
            BOOST_THROW_EXCEPTION(std::runtime_error("No touches"));
        else if (current_touches.size() == 1)
            return current_touches.begin()->second.coordinates;
        else
            BOOST_THROW_EXCEPTION(std::runtime_error("More than one touches"));
    };

    std::optional<uint32_t> latest_serial() const
    {
        return latest_serial_;
    }

    bool pointer_events_pending() const
    {
        return !pending_buttons.empty() || pending_pointer_location;
    }

    bool touch_events_pending() const
    {
        return !pending_touches.empty() || !pending_up_touches.empty();
    }

    void add_pointer_enter_notification(PointerEnterNotifier const& on_enter)
    {
        enter_notifiers.push_back(on_enter);
    }
    void add_pointer_leave_notification(PointerLeaveNotifier const& on_leave)
    {
        leave_notifiers.push_back(on_leave);
    }
    void add_pointer_motion_notification(PointerMotionNotifier const& on_motion)
    {
        motion_notifiers.push_back(on_motion);
    }
    void add_pointer_button_notification(PointerButtonNotifier const& on_button)
    {
        button_notifiers.push_back(on_button);
    }

    void* bind_if_supported(wl_interface const& to_bind, VersionSpecifier const& version) const
    {
        std::optional<bool> expected_to_be_supported{};

        if (supported_extensions)
        {
            expected_to_be_supported =
                supported_extensions->count(to_bind.name) &&
                version.select_version(supported_extensions->at(to_bind.name), to_bind.version);
        }

        /* TODO: Mark tests using globals which exist, but are listed as unsupported as
         * may-fail.
         * This should help incrementally implementing a protocol, while getting test
         * feedback.
         */
        auto const global = globals.find(to_bind.name);
        if (global != globals.end())
        {
            auto const version_to_bind = version.select_version(global->second.version, to_bind.version);
            if (version_to_bind)
            {
                auto global_proxy = wl_registry_bind(registry, global->second.id, &to_bind, version_to_bind.value());
                if (!global_proxy)
                {
                    throw_wayland_error(display);
                }
                return global_proxy;
            }
            else if (!expected_to_be_supported.value_or(true))
            {
                // We didn't expect to find the needed version of this extension anyway…
                BOOST_THROW_EXCEPTION((ExtensionExpectedlyNotSupported{to_bind.name, version}));
            }

            BOOST_THROW_EXCEPTION((std::runtime_error{
                "Failed to bind to " + std::string{to_bind.name} + " version " + version.describe()}));
        }
        else if (!expected_to_be_supported.value_or(true))
        {
            // We didn't expect to find this extension anyway…
            BOOST_THROW_EXCEPTION((ExtensionExpectedlyNotSupported{to_bind.name, version}));
        }
        BOOST_THROW_EXCEPTION((std::runtime_error{
            "Failed to bind to " + std::string{to_bind.name} + " version " + version.describe()}));
    }

    void dispatch_until(
        std::function<bool()> const& predicate, std::chrono::seconds timeout)
    {
        using namespace std::chrono;

        auto const end_time = steady_clock::now() + timeout;
        while (!predicate())
        {
            while (wl_display_prepare_read(display) != 0)
            {
                if (wl_display_dispatch_pending(display) < 0)
                    throw_wayland_error(display);
            }
            wl_display_flush(display);

            auto const time_left = end_time - steady_clock::now();
            if (time_left.count() < 0)
            {
                BOOST_THROW_EXCEPTION((Timeout{"Timeout waiting for condition"}));
            }

            /*
             * TODO: We really want std::chrono::duration::ceil() here, but that's C++17
             */
            /*
             * We want to wait *at least* as long as time_left. duration_cast<milliseconds>
             * will perform integer division, so any fractional milliseconds will get dropped.
             *
             * Adding 1ms will ensure we wait until *after* we're meant to timeout.
             */
            auto const maximum_wait_ms = duration_cast<milliseconds>(time_left) + 1ms;
            pollfd fd{
                wl_display_get_fd(display),
                POLLIN | POLLERR,
                0
            };

            auto const poll_result = poll(&fd, 1, maximum_wait_ms.count());
            if (poll_result < 0)
            {
                wl_display_cancel_read(display);
                BOOST_THROW_EXCEPTION((std::system_error{
                    errno,
                    std::system_category(),
                    "Failed to wait for Wayland event"}));
            }

            if (poll_result == 0)
            {
                wl_display_cancel_read(display);
                BOOST_THROW_EXCEPTION((Timeout{"Timeout waiting for condition"}));
            }

            if (wl_display_read_events(display) < 0)
            {
                throw_wayland_error(display);
            }

            if (wl_display_dispatch_pending(display) < 0)
            {
                throw_wayland_error(display);
            }
        }
    }

    void server_roundtrip()
    {
        if (wl_display_roundtrip(display) < 0)
        {
            throw_wayland_error(display);
        }
    }

    void client_flush()
    {
        if (wl_display_flush(display) == -1)
        {
            /* flush will return a (non-fatal) EAGAIN if the send buffer is
             * full.
             *
             * We don't particularly want to care about the EAGAIN case
             * at the moment, so just ignore it.
             */
            if (errno != EAGAIN)
            {
                throw_wayland_error(display);
            }
        }
    }

    struct Output
    {
        OutputState current;
        OutputState pending;
        std::vector<std::function<void()>> done_notifiers;

        Output(struct wl_output* output)
            : current{output},
              pending{output}
        {
        }

        static void geometry_thunk(
            void* ctx,
            struct wl_output */*wl_output*/,
            int32_t x,
            int32_t y,
            int32_t /*physical_width*/,
            int32_t /*physical_height*/,
            int32_t /*subpixel*/,
            const char */*make*/,
            const char */*model*/,
            int32_t /*transform*/)
        {
            auto me = static_cast<Output*>(ctx);
            me->pending.geometry_position = std::make_pair(x, y);
        }

        static void mode_thunk(
            void* ctx,
            struct wl_output */*wl_output*/,
            uint32_t /*flags*/,
            int32_t width,
            int32_t height,
            int32_t /*refresh*/)
        {
            auto me = static_cast<Output*>(ctx);
            me->pending.mode_size = std::make_pair(width, height);
        }

        static void done_thunk(void* ctx, struct wl_output */*wl_output*/)
        {
            auto me = static_cast<Output*>(ctx);

            if (me->pending.geometry_position)
                me->current.geometry_position = me->pending.geometry_position;
            if (me->pending.mode_size)
                me->current.mode_size = me->pending.mode_size;
            if (me->pending.scale)
                me->current.scale = me->pending.scale;

            me->pending = OutputState{me->current.output};

            for (auto const& notifier : me->done_notifiers)
                notifier();
        }

        static void scale_thunk(void* ctx, struct wl_output */*wl_output*/, int32_t factor)
        {
            auto me = static_cast<Output*>(ctx);
            me->pending.scale = factor;
        }

        static constexpr wl_output_listener listener = {
            &Impl::Output::geometry_thunk,
            &Impl::Output::mode_thunk,
            &Impl::Output::done_thunk,
            &Impl::Output::scale_thunk,
        };
    };

    std::vector<std::unique_ptr<Output>> outputs;

private:
    static void keyboard_keymap(void*, wl_keyboard*, uint32_t, int32_t fd, uint32_t)
    {
        close(fd);
    }

    static void keyboard_enter(
        void* ctx,
        wl_keyboard*,
        uint32_t serial,
        wl_surface *surface,
        wl_array* /*keys*/)
    {
        auto me = static_cast<Impl*>(ctx);
        me->keyboard_focused_surface = surface;
        me->latest_serial_ = serial;
    }

    static void keyboard_leave(
        void *ctx,
        wl_keyboard*,
        uint32_t serial,
        wl_surface* surface)
    {
        auto me = static_cast<Impl*>(ctx);
        if (me->keyboard_focused_surface == surface)
        {
            me->keyboard_focused_surface = nullptr;
        }
        me->latest_serial_ = serial;
    }

    static void keyboard_key(
        void* ctx,
        wl_keyboard*,
        uint32_t serial,
        uint32_t /*time*/,
        uint32_t /*key*/,
        uint32_t /*state*/)
    {
        auto me = static_cast<Impl*>(ctx);
        me->latest_serial_ = serial;
    }

    static void keyboard_modifiers(void*, wl_keyboard*, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
    {
    }

    static void keyboard_repeat_info(void*, wl_keyboard*, int32_t, int32_t)
    {
    }

    static constexpr wl_keyboard_listener keyboard_listener = {
        keyboard_keymap,
        keyboard_enter,
        keyboard_leave,
        keyboard_key,
        keyboard_modifiers,
        keyboard_repeat_info,
    };

    static void pointer_enter(
        void* ctx,
        wl_pointer* /*pointer*/,
        uint32_t serial,
        wl_surface* surface,
        wl_fixed_t x,
        wl_fixed_t y)
    {
        auto me = static_cast<Impl*>(ctx);
        me->latest_serial_ = serial;

        if (me->current_pointer_location && !me->pending_pointer_leave)
            FAIL()
                << "Pointer tried to enter surface " << surface
                << " without first leaving surface " << me->current_pointer_location.value().surface;

        me->pending_pointer_location = SurfaceLocation{
            surface,
            std::make_pair(x, y)
        };
    }

    static void pointer_leave(
        void* ctx,
        wl_pointer* /*pointer*/,
        uint32_t serial,
        wl_surface* surface)
    {
        auto me = static_cast<Impl*>(ctx);
        me->latest_serial_ = serial;

        if (!me->current_pointer_location)
            FAIL() << "Got wl_pointer.leave when the pointer was not on a surface";

        // the surface should never be null along the wire, but may come out as null if it's been destroyed
        if (surface != nullptr && surface != me->current_pointer_location.value().surface)
            FAIL()
                << "Got wl_pointer.leave with surface " << surface
                << " instead of " << me->current_pointer_location.value().surface;

        me->pending_pointer_location = std::nullopt;
        me->pending_pointer_leave = true;
    }

    static void pointer_motion(
        void* ctx,
        wl_pointer* /*pointer*/,
        uint32_t /*time*/,
        wl_fixed_t x,
        wl_fixed_t y)
    {
        auto me = static_cast<Impl*>(ctx);

        if (!me->current_pointer_location && !me->pending_pointer_location)
            FAIL() << "Got wl_pointer.motion when the pointer was not on a surface";

        if (!me->pending_pointer_location)
            me->pending_pointer_location = me->current_pointer_location;
        me->pending_pointer_location.value().coordinates = std::make_pair(x, y);
    }

    static void pointer_button(
        void *ctx,
        wl_pointer* /*wl_pointer*/,
        uint32_t serial,
        uint32_t /*time*/,
        uint32_t button,
        uint32_t state)
    {
        auto me = static_cast<Impl*>(ctx);
        me->latest_serial_ = serial;

        me->pending_buttons[button] = std::make_pair(serial, state == WL_POINTER_BUTTON_STATE_PRESSED);
    }

    static void pointer_frame(void* ctx, wl_pointer* /*pointer*/)
    {
        auto me = static_cast<Impl*>(ctx);

        if (me->pending_pointer_leave)
        {
            if (!me->current_pointer_location)
                FAIL() << "Pointer tried to leave when it was not on a surface";

            wl_surface* old_surface = me->current_pointer_location.value().surface;
            me->current_pointer_location = std::nullopt;
            me->pending_pointer_leave = false;

            me->notify_of_pointer_leave(old_surface);
        }

        if (me->pending_pointer_location)
        {
            auto const old_pointer_location = me->current_pointer_location;
            me->current_pointer_location = me->pending_pointer_location;
            me->pending_pointer_location = std::nullopt;

            if (!old_pointer_location)
            {
                me->notify_of_pointer_enter(
                    me->current_pointer_location.value().surface,
                    me->current_pointer_location.value().coordinates);
            }
            else
            {
                me->notify_of_pointer_motion(me->current_pointer_location.value().coordinates);
            }
        }

        if (!me->pending_buttons.empty())
        {
            me->notify_of_pointer_buttons(me->pending_buttons);
            me->pending_buttons.clear();
        }
    }

    void notify_of_pointer_enter(wl_surface* surface, std::pair<int, int> position)
    {
        enter_notifiers.erase(
            std::remove_if(
                enter_notifiers.begin(),
                enter_notifiers.end(),
                // FIXME: copy `position` to avoid a GCC-15 bug yielding
                // `-Wuninitialized` under `--sanitize=undefined` on armhf
                [&, position](auto const& notifier)
                {
                    return !notifier(surface, position.first, position.second);
                }),
            enter_notifiers.end()
        );
    }

    void notify_of_pointer_leave(wl_surface* surface)
    {
        leave_notifiers.erase(
            std::remove_if(
                leave_notifiers.begin(),
                leave_notifiers.end(),
                [&](auto const& notifier)
                {
                    return !notifier(surface);
                }),
            leave_notifiers.end()
        );
    }

    void notify_of_pointer_motion(std::pair<int, int> position)
    {
        motion_notifiers.erase(
            std::remove_if(
                motion_notifiers.begin(),
                motion_notifiers.end(),
                [&](auto const& notifier)
                {
                    return !notifier(position.first, position.second);
                }),
            motion_notifiers.end()
        );
    }

    void notify_of_pointer_buttons(std::map<uint32_t, std::pair<uint32_t, bool>> const& buttons)
    {
        for (auto const& button : buttons)
        {
            button_notifiers.erase(
                std::remove_if(
                    button_notifiers.begin(),
                    button_notifiers.end(),
                    [&](auto const& notifier)
                    {
                        return !notifier(button.second.first, button.first, button.second.second);
                    }),
                button_notifiers.end()
            );
        }
    }

    static constexpr wl_pointer_listener pointer_listener = {
        &Impl::pointer_enter,
        &Impl::pointer_leave,
        &Impl::pointer_motion,
        &Impl::pointer_button,
        [](auto...){},  // axis
        &Impl::pointer_frame,    // frame
        [](auto...){},  // axis_source
        [](auto...){},  // axis_stop
        [](auto...){},  // axis_discrete
    };

    static void touch_down(
        void* ctx,
        wl_touch* /*wl_touch*/,
        uint32_t serial,
        uint32_t /*time*/,
        wl_surface* surface,
        int32_t id,
        wl_fixed_t x,
        wl_fixed_t y)
    {
        auto me = static_cast<Impl*>(ctx);
        me->latest_serial_ = serial;

        auto touch = me->current_touches.find(id);
        if (touch != me->current_touches.end())
            FAIL() << "Got wl_touch.down with ID " << id << " which is already down";

        me->pending_touches[id] = SurfaceLocation {
            surface,
            std::make_pair(x,y)
        };
    }

    static void touch_up(
        void* ctx,
        wl_touch* /*wl_touch*/,
        uint32_t serial,
        uint32_t /*time*/,
        int32_t id)
    {
        auto me = static_cast<Impl*>(ctx);
        me->latest_serial_ = serial;

        auto touch = me->current_touches.find(id);
        if (touch == me->current_touches.end())
            FAIL() << "Got wl_touch.up with unknown ID " << id;

        me->pending_up_touches.insert(id);
    }

	static void touch_motion(
        void* ctx,
        wl_touch* /*wl_touch*/,
        uint32_t /*time*/,
        int32_t id,
        wl_fixed_t x,
        wl_fixed_t y)
    {
        auto me = static_cast<Impl*>(ctx);

        auto touch = me->current_touches.find(id);
        if (touch == me->current_touches.end())
            FAIL() << "Got wl_touch.up with unknown ID " << id;

        me->pending_touches[id] = SurfaceLocation {
            touch->second.surface,
            std::make_pair(x,y)
        };
    }

    static void touch_frame(void* ctx, wl_touch* /*touch*/)
    {
        auto me = static_cast<Impl*>(ctx);

        for (auto const& id : me->pending_up_touches)
        {
            me->current_touches.erase(id);
        }

        for (auto const& touch : me->pending_touches)
        {
            me->current_touches[touch.first] = touch.second;
        }

        me->pending_up_touches.clear();
        me->pending_touches.clear();
    }

    static constexpr wl_touch_listener touch_listener = {
        &Impl::touch_down,
        &Impl::touch_up,
        &Impl::touch_motion,
        &Impl::touch_frame,
        nullptr,    // cancel
        nullptr,    // shape
        nullptr,    // orientation
    };

    static void seat_capabilities(
        void* ctx,
        struct wl_seat* seat,
        uint32_t capabilities)
    {
        auto me = static_cast<Impl*>(ctx);

        if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
        {
            me->keyboard = wl_seat_get_keyboard(seat);
            wl_keyboard_add_listener(me->keyboard, &keyboard_listener, me);
        }

        if (capabilities & WL_SEAT_CAPABILITY_POINTER)
        {
            me->pointer = wl_seat_get_pointer(seat);
            wl_pointer_add_listener(me->pointer, &pointer_listener, me);
        }

        if (capabilities & WL_SEAT_CAPABILITY_TOUCH)
        {
            me->touch = wl_seat_get_touch(seat);
            wl_touch_add_listener(me->touch, &touch_listener, me);
        }
    }

    static void seat_name(
        void*,
        struct wl_seat*,
        char const*)
    {
    }

    static constexpr wl_seat_listener seat_listener = {
        &Impl::seat_capabilities,
        &Impl::seat_name
    };

    static void global_handler(
        void* ctx,
        wl_registry* registry,
        uint32_t id,
        char const* interface,
        uint32_t version)
    {
        using namespace std::literals::string_literals;

        static auto const safe_bind = []
            (wl_registry* registry, uint32_t name, const wl_interface* iface, uint32_t version)
        {
            return wl_registry_bind(registry, name, iface, std::min(version, static_cast<uint32_t>(iface->version)));
        };

        auto me = static_cast<Impl*>(ctx);
        me->global_type_names[id] = interface;
        me->globals[interface] = Global{id, version};

        if ("wl_shm"s == interface)
        {
            me->shm = static_cast<struct wl_shm*>(safe_bind(registry, id, &wl_shm_interface, version));
        }
        else if ("wl_compositor"s == interface)
        {
            me->compositor = static_cast<struct wl_compositor*>(
                safe_bind(registry, id, &wl_compositor_interface, version));
        }
        else if ("wl_subcompositor"s == interface)
        {
            me->subcompositor = static_cast<struct wl_subcompositor*>(
                safe_bind(registry, id, &wl_subcompositor_interface, version));
        }
        else if ("wl_shell"s == interface)
        {
            me->shell = static_cast<wl_shell*>(safe_bind(registry, id, &wl_shell_interface, version));
        }
        else if ("wl_seat"s == interface)
        {
            me->seat = static_cast<struct wl_seat*>(safe_bind(registry, id, &wl_seat_interface, version));

            wl_seat_add_listener(me->seat, &seat_listener, me);
            // Ensure we receive the initial seat events.
            me->server_roundtrip();
        }
        else if ("wl_output"s == interface)
        {
            auto wl_output = static_cast<struct wl_output*>(safe_bind(registry, id, &wl_output_interface, version));
            auto output = std::make_unique<Output>(wl_output);
            wl_output_add_listener(wl_output, &Output::listener, output.get());
            me->outputs.push_back(std::move(output));

            // Ensure we receive the initial output events.
            me->server_roundtrip();
        }
        else if ("zxdg_shell_v6"s == interface)
        {
            me->xdg_shell_v6 = static_cast<zxdg_shell_v6*>(safe_bind(registry, id, &zxdg_shell_v6_interface, version));
        }
        else if ("xdg_wm_base"s == interface)
        {
            me->xdg_shell_stable = static_cast<xdg_wm_base*>(safe_bind(registry, id, &xdg_wm_base_interface, version));
        }
    }

    static void global_removed(void* ctx, wl_registry*, uint32_t id)
    {
        auto me = static_cast<Impl*>(ctx);
        auto const name = me->global_type_names.find(id);
        if (name != me->global_type_names.end())
        {
            me->globals.erase(name->second);
            me->global_type_names.erase(name);
        }
    }

    constexpr static wl_registry_listener registry_listener = {
        &global_handler,
        &global_removed
    };

    std::shared_ptr<std::unordered_map<std::string, uint32_t> const> const supported_extensions;

    struct wl_display* display;
    struct wl_registry* registry = nullptr;
    struct wl_compositor* compositor = nullptr;
    struct wl_subcompositor* subcompositor = nullptr;
    struct wl_shm* shm = nullptr;
    struct wl_shell* shell = nullptr;
    struct wl_seat* seat = nullptr;
    struct wl_keyboard* keyboard = nullptr;
    struct wl_pointer* pointer = nullptr;
    struct wl_touch* touch = nullptr;
    struct zxdg_shell_v6* xdg_shell_v6 = nullptr;
    std::vector<std::function<void()>> destruction_callbacks;
    struct xdg_wm_base* xdg_shell_stable = nullptr;

    struct Global
    {
        uint32_t id;
        uint32_t version;
    };
    std::map<std::string, Global> globals;
    std::map<uint32_t, std::string> global_type_names;

    struct SurfaceLocation
    {
        wl_surface* surface;
        std::pair<wl_fixed_t, wl_fixed_t> coordinates;
    };
    wl_surface* keyboard_focused_surface = nullptr;
    std::optional<SurfaceLocation> current_pointer_location;
    std::optional<SurfaceLocation> pending_pointer_location;
    bool pending_pointer_leave{false};
    std::map<uint32_t, std::pair<uint32_t, bool>> pending_buttons; ///< Maps button id to the serial and if it's down
    std::map<int, SurfaceLocation> current_touches; ///< Touches that have gotten a frame event
    std::map<int, SurfaceLocation> pending_touches; ///< Touches that have gotten down or motion events without a frame
    std::set<int> pending_up_touches; ///< Touches that have gotten up events without a frame
    std::optional<uint32_t> latest_serial_;

    std::vector<PointerEnterNotifier> enter_notifiers;
    std::vector<PointerLeaveNotifier> leave_notifiers;
    std::vector<PointerMotionNotifier> motion_notifiers;
    std::vector<PointerButtonNotifier> button_notifiers;
};

constexpr wl_keyboard_listener wlcs::Client::Impl::keyboard_listener;
constexpr wl_pointer_listener wlcs::Client::Impl::pointer_listener;
constexpr wl_touch_listener wlcs::Client::Impl::touch_listener;
constexpr wl_seat_listener wlcs::Client::Impl::seat_listener;
constexpr wl_output_listener wlcs::Client::Impl::Output::listener;
constexpr wl_registry_listener wlcs::Client::Impl::registry_listener;

wlcs::Client::Client(Server& server)
    : impl{std::make_unique<Impl>(server)}
{
}

wlcs::Client::~Client() = default;

wlcs::Client::operator wl_display*() const
{
    return impl->wl_display();
}

wl_compositor* wlcs::Client::compositor() const
{
    return impl->wl_compositor();
}

wl_subcompositor* wlcs::Client::subcompositor() const
{
    return impl->wl_subcompositor();
}

wl_shm* wlcs::Client::shm() const
{
    return impl->wl_shm();
}

wl_seat* wlcs::Client::seat() const
{
    return impl->wl_seat();
}

void wlcs::Client::run_on_destruction(std::function<void()> callback)
{
    impl->run_on_destruction(callback);
}

wlcs::ShmBuffer const& wlcs::Client::create_buffer(int width, int height)
{
    return impl->create_buffer(*this, width, height);
}

wlcs::Surface wlcs::Client::create_wl_shell_surface(int width, int height)
{
    return impl->create_wl_shell_surface(*this, width, height);
}

wlcs::Surface wlcs::Client::create_xdg_shell_v6_surface(int width, int height)
{
    return impl->create_xdg_shell_v6_surface(*this, width, height);
}

wlcs::Surface wlcs::Client::create_xdg_shell_stable_surface(int width, int height)
{
    return impl->create_xdg_shell_stable_surface(*this, width, height);
}

wlcs::Surface wlcs::Client::create_visible_surface(int width, int height)
{
    return impl->create_visible_surface(*this, width, height);
}

size_t wlcs::Client::output_count() const
{
    return impl->outputs.size();
}

wlcs::OutputState wlcs::Client::output_state(size_t index) const
{
    if (index > output_count())
        throw std::out_of_range("Invalid output index");

    return impl->outputs[index]->current;
}

void wlcs::Client::add_output_done_notifier(size_t index, std::function<void()> const& notifier)
{
    if (index > output_count())
        throw std::runtime_error("Invalid output index");

    impl->outputs[index]->done_notifiers.push_back(notifier);
}

wl_shell* wlcs::Client::shell() const
{
    return impl->the_shell();
}

zxdg_shell_v6* wlcs::Client::xdg_shell_v6() const
{
    return impl->the_xdg_shell_v6();
}

xdg_wm_base* wlcs::Client::xdg_shell_stable() const
{
    return impl->the_xdg_shell_stable();
}

wl_surface* wlcs::Client::keyboard_focused_window() const
{
    return impl->keyboard_focused_window();
}

wl_surface* wlcs::Client::window_under_cursor() const
{
    return impl->window_under_cursor();
}

wl_surface* wlcs::Client::touched_window() const
{
    return impl->touched_window();
}

std::pair<wl_fixed_t, wl_fixed_t> wlcs::Client::pointer_position() const
{
    return impl->pointer_position();
}

std::pair<wl_fixed_t, wl_fixed_t> wlcs::Client::touch_position() const
{
    return impl->touch_position();
}

std::optional<uint32_t> wlcs::Client::latest_serial() const
{
    return impl->latest_serial();
}

void wlcs::Client::add_pointer_enter_notification(PointerEnterNotifier const& on_enter)
{
    impl->add_pointer_enter_notification(on_enter);
}

void wlcs::Client::add_pointer_leave_notification(PointerLeaveNotifier const& on_leave)
{
    impl->add_pointer_leave_notification(on_leave);
}

void wlcs::Client::add_pointer_motion_notification(PointerMotionNotifier const& on_motion)
{
    impl->add_pointer_motion_notification(on_motion);
}

void wlcs::Client::add_pointer_button_notification(PointerButtonNotifier const& on_button)
{
    impl->add_pointer_button_notification(on_button);
}

void wlcs::Client::dispatch_until(std::function<bool()> const& predicate, std::chrono::seconds timeout)
{
    impl->dispatch_until(predicate, timeout);
}

void wlcs::Client::roundtrip()
{
    impl->server_roundtrip();
}

void wlcs::Client::flush()
{
    impl->client_flush();
}

void* wlcs::Client::bind_if_supported(wl_interface const& interface, VersionSpecifier const& version) const
{
    return impl->bind_if_supported(interface, version);
}

wl_pointer* wlcs::Client::the_pointer() const
{
    return impl->the_pointer();
}

class wlcs::Surface::Impl
{
public:
    Impl(Client& client)
        : surface_{wl_compositor_create_surface(client.compositor())},
          owner_{client}
    {
        wl_surface_add_listener(surface_, &surface_listener, this);
    }

    ~Impl()
    {
        for (auto i = 0u; i < pending_callbacks.size(); )
        {
            if (pending_callbacks[i].first == this)
            {
                auto pending_callback = pending_callbacks[i].second;
                delete static_cast<std::function<void(uint32_t)>*>(wl_callback_get_user_data(pending_callback));

                wl_callback_destroy(pending_callback);
                pending_callbacks.erase(pending_callbacks.begin() + i);
            }
            else
            {
                ++i;
            }
        }

        for (auto const& callback: destruction_callbacks)
            callback();
        destruction_callbacks.clear();

        wl_surface_destroy(surface_);
    }

    ::wl_surface* surface() const
    {
        return surface_;
    }

    void attach_buffer(int width, int height)
    {
        auto& buffer = owner_.create_buffer(width, height);
        wl_surface_attach(surface_, buffer, 0, 0);
    }

    void add_frame_callback(std::function<void(uint32_t)> const& on_frame)
    {
        std::unique_ptr<std::function<void(uint32_t)>> holder{
            new std::function<void(uint32_t)>(on_frame)};

        auto callback = wl_surface_frame(surface_);

        pending_callbacks.push_back(std::make_pair(this, callback));

        wl_callback_add_listener(callback, &frame_listener, holder.release());
    }

    void attach_visible_buffer(int width, int height)
    {
        attach_buffer(width, height);
        auto surface_rendered = std::make_shared<bool>(false);
        add_frame_callback([surface_rendered](auto) { *surface_rendered = true; });
        wl_surface_commit(surface_);
        owner_.dispatch_until([surface_rendered]() { return *surface_rendered; });
    }

    void run_on_destruction(std::function<void()> callback)
    {
        destruction_callbacks.push_back(callback);
    }

    Client& owner() const
    {
        return owner_;
    }

    auto current_outputs() -> std::set<wl_output*> const&
    {
        return outputs;
    }

private:

    static std::vector<std::pair<Impl const*, wl_callback*>> pending_callbacks;
    std::set<wl_output*> outputs;

    static void frame_callback(void* ctx, wl_callback* callback, uint32_t frame_time)
    {
        auto us = std::find_if(
            pending_callbacks.begin(),
            pending_callbacks.end(),
            [callback](auto const& elem)
            {
                return elem.second == callback;
            });
        pending_callbacks.erase(us);

        auto frame_callback = static_cast<std::function<void(uint32_t)>*>(ctx);

        (*frame_callback)(frame_time);

        wl_callback_destroy(callback);
        delete frame_callback;
    }

    static constexpr wl_callback_listener frame_listener = {
        &frame_callback
    };

    static void on_enter(void* data, ::wl_surface* /*wl_surface*/, wl_output* output)
    {
        auto const self = static_cast<Impl*>(data);

        auto const inserted = self->outputs.insert(output);

        if (!inserted.second)
        {
            BOOST_THROW_EXCEPTION(std::runtime_error(
                "Got wl_surface.enter(wl_output@" +
                std::to_string(wl_proxy_get_id(reinterpret_cast<wl_proxy*>(output))) +
                ") for an output the surface is already on"));
        }
    }

    static void on_leave(void* data, ::wl_surface* /*wl_surface*/, wl_output* output)
    {
        auto const self = static_cast<Impl*>(data);

        auto const erased = self->outputs.erase(output);

        if (!erased)
        {
            BOOST_THROW_EXCEPTION(std::runtime_error(
                "Got wl_surface.leave(wl_output@" +
                std::to_string(wl_proxy_get_id(reinterpret_cast<wl_proxy*>(output))) +
                ") for an output the surface is not on"));
        }
    }

    static constexpr wl_surface_listener surface_listener{
        &on_enter,
        &on_leave,
    };

    struct wl_surface* const surface_;
    Client& owner_;
    std::vector<std::function<void()>> destruction_callbacks;
};

std::vector<std::pair<wlcs::Surface::Impl const*, wl_callback*>> wlcs::Surface::Impl::pending_callbacks;

constexpr wl_callback_listener wlcs::Surface::Impl::frame_listener;
constexpr wl_surface_listener wlcs::Surface::Impl::surface_listener;

wlcs::Surface::Surface(Client& client)
    : impl{std::make_unique<Impl>(client)}
{
}

wlcs::Surface::~Surface() = default;

wlcs::Surface::Surface(Surface&&) = default;

wlcs::Surface::operator ::wl_surface*() const
{
    return impl->surface();
}

void wlcs::Surface::attach_buffer(int width, int height)
{
    impl->attach_buffer(width, height);
}

void wlcs::Surface::add_frame_callback(std::function<void(int)> const& on_frame)
{
    impl->add_frame_callback(on_frame);
}

void wlcs::Surface::attach_visible_buffer(int width, int height)
{
    impl->attach_visible_buffer(width, height);
}

void wlcs::Surface::run_on_destruction(std::function<void()> callback)
{
    impl->run_on_destruction(callback);
}

wlcs::Client& wlcs::Surface::owner() const
{
    return impl->owner();
}

auto wlcs::Surface:: current_outputs() -> std::set<wl_output*> const&
{
    return impl->current_outputs();
}

class wlcs::Subsurface::Impl
{
public:
    Impl(Client& client, Surface& surface, Surface& parent)
        : subsurface_{wl_subcompositor_get_subsurface(client.subcompositor(), surface, parent)},
          parent_{parent}
    {
    }

    ~Impl()
    {
        wl_subsurface_destroy(subsurface_);
    }

    struct wl_subsurface* const subsurface_;
    Surface& parent_;
};

wlcs::Subsurface wlcs::Subsurface::create_visible(Surface& parent, int x, int y, int width, int height)
{
    wlcs::Subsurface subsurface{parent};
    wl_subsurface_set_position(subsurface, x, y);

    subsurface.attach_buffer(width, height);

    bool surface_rendered{false};
    subsurface.add_frame_callback([&surface_rendered](auto) { surface_rendered = true; });
    wlcs::Surface* surface_ptr = &subsurface;
    while (surface_ptr)
    {
        wl_surface_commit(*surface_ptr);
        auto subsurface_ptr = dynamic_cast<wlcs::Subsurface*>(surface_ptr);
        if (subsurface_ptr)
            surface_ptr = &subsurface_ptr->parent();
        else
            surface_ptr = nullptr;
    }
    parent.owner().dispatch_until([&surface_rendered]() { return surface_rendered; });

    return subsurface;
}

wlcs::Subsurface::Subsurface(wlcs::Surface& parent)
    : Surface{parent.owner()},
      impl{std::make_unique<wlcs::Subsurface::Impl>(parent.owner(), *this, parent)}
{
}

wlcs::Subsurface::Subsurface(Subsurface &&) = default;

wlcs::Subsurface::~Subsurface() = default;

wlcs::Subsurface::operator wl_subsurface*() const
{
    return impl->subsurface_;
}

wlcs::Surface& wlcs::Subsurface::parent() const
{
    return impl->parent_;
}

class wlcs::ShmBuffer::Impl
{
public:
    Impl(Client& client, int width, int height)
    {
        auto stride = width * 4;
        auto size = stride * height;
        auto fd = wlcs::helpers::create_anonymous_file(size);

        auto pool = wl_shm_create_pool(client.shm(), fd, size);
        buffer_ = wl_shm_pool_create_buffer(
            pool,
            0,
            width,
            height,
            stride,
            WL_SHM_FORMAT_ARGB8888);
        wl_shm_pool_destroy(pool);
        close(fd);

        wl_buffer_add_listener(buffer_, &listener, this);
    }

    ~Impl()
    {
        wl_buffer_destroy(buffer_);
    }

    wl_buffer* buffer() const
    {
        return buffer_;
    }

    void add_release_listener(std::function<bool()> const& on_release)
    {
        release_notifiers.push_back(on_release);
    }

private:
    static void on_release(void* ctx, wl_buffer* /*buffer*/)
    {
        auto me = static_cast<Impl*>(ctx);

        std::vector<decltype(me->release_notifiers.begin())> expired_notifiers;

        for (auto notifier = me->release_notifiers.begin(); notifier != me->release_notifiers.end(); ++notifier)
        {
            if (!(*notifier)())
            {
                expired_notifiers.push_back(notifier);
            }
        }
        for (auto const& expired : expired_notifiers)
            me->release_notifiers.erase(expired);
    }

    static constexpr wl_buffer_listener listener {
        &on_release
    };

    wl_buffer* buffer_;
    std::vector<std::function<bool()>> release_notifiers;
};

constexpr wl_buffer_listener wlcs::ShmBuffer::Impl::listener;

wlcs::ShmBuffer::ShmBuffer(Client &client, int width, int height)
    : impl{std::make_unique<Impl>(client, width, height)}
{
}

wlcs::ShmBuffer::ShmBuffer(ShmBuffer&&) = default;
wlcs::ShmBuffer::~ShmBuffer() = default;

wlcs::ShmBuffer::operator wl_buffer*() const
{
    return impl->buffer();
}

void wlcs::ShmBuffer::add_release_listener(std::function<bool()> const &on_release)
{
    impl->add_release_listener(on_release);
}

wlcs::OutputState::OutputState(wl_output* output) : output{output}
{
}
