// =====================================================================================================================
//  fennec, a free and open source game engine
//  Copyright © 2025 - 2026  Medusa Slockbower
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================

///
/// \file fennec/platform/linux/wayland/server.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///

#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H

#include <fennec/platform/linux/wayland/forward.h>
#include <fennec/platform/interface/display_server.h>

#if FENNEC_HAS_LIBDECOR
#include <fennec/platform/linux/wayland/libdecor/libdecor.h>
#endif

#ifndef FENNEC_DOXYGEN
// forward defs to avoid flooding global namespace
struct wl_display;
struct wl_shm;
struct wl_compositor;
struct wl_registry;
struct wl_seat;

struct wp_viewporter;
struct xdg_wm_base;
#endif

namespace fennec
{

///
/// \brief Class for handling the Wayland Display Server
class wayland_server : public display_server_base<wayland_server, wayland_window> {

// Constructors & Destructor ===========================================================================================
public:

	/// \name Constructors & Destructor
	/// @{

	/// \brief constructor
	/// \param p the platform
	explicit wayland_server(fennec::platform* p);

	/// \brief destructor
	~wayland_server() override;

	/// @}


// Operations ==========================================================================================================
public:

	/// \name Operations
	/// @{

	void connect() override;         //!< connect to wayland
	void disconnect() override;      //!< disconnect from wayland
	bool connected() const override; //!< check if connected to wayland \returns \emph{true} if connected, \emph{false} otherwise

	void dispatch() override; //!< dispatch the current context

	/// \brief create a window
	/// \param conf the configuration
	/// \param parent the parent window
	/// \returns a new window with the provided configuration and parent
	window* create_window(const window::config& conf, window* parent) override;

	/// \returns the native wl_display handle
	void* get_native_handle() override { return display; }

	/// @}

// Private Member Variables ============================================================================================
private:
	wl_display*    display;
	wl_registry*   registry;

	wl_compositor* compositor;
	xdg_wm_base*   xdg;
	wl_seat*       seat;
	bool           fifo, has_libdecor;

#if FENNEC_HAS_LIBDECOR
	libdecor* libdecor;
#endif


// Listeners ===========================================================================================================
private:

	static void _wl_registry_listen_global(void*, wl_registry*, uint32_t, const char*, uint32_t);
	static void _wl_registry_on_global_remove(void*, wl_registry*, uint32_t);

	static void _wl_seat_listen_capabilities(void*, wl_seat*, uint32_t);
	static void _wl_seat_listen_name(void*, wl_seat*, const char*);

	static void _xdg_listen_ping(void*, xdg_wm_base*, uint32_t);

#if FENNEC_HAS_LIBDECOR
	static void _libdecor_on_error(struct libdecor*, libdecor_error error, const char* message);
#endif

	FENNEC_RTTI_CLASS_ENABLE(display_server) {
		display_server::register_type<wayland_server>(1);
	}

	friend class wayland_window;
};

}

#endif // FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H
