#ifndef EDITSCENE_EVENT_BUS_HPP
#define EDITSCENE_EVENT_BUS_HPP
#pragma once

#include "../components/EventParams.hpp"
#include <Ogre.h>
#include <cstdint>
#include <functional>
#include <unordered_map>
#include <vector>

/**
 * Global synchronous event bus.
 *
 * Subscribers register callbacks by event name. When an event is sent,
 * all matching callbacks are invoked immediately in the send() call.
 *
 * Payload is an EventParams — a tagged union map supporting entity IDs,
 * integers, floats, doubles, strings, and arrays of each type.
 */
class EventBus {
public:
	using ListenerId = uint64_t;
	using Callback =
		std::function<void(const Ogre::String &eventName,
				   const editScene::EventParams &params)>;

	static EventBus &getInstance();

	/** Subscribe to an event. Returns a handle for unsubscribe(). */
	ListenerId subscribe(const Ogre::String &eventName, Callback cb);

	/** Unsubscribe by handle. Safe to call with invalid id. */
	void unsubscribe(ListenerId id);

	/** Send an event with an EventParams payload. */
	void send(const Ogre::String &eventName,
		  const editScene::EventParams &params = {});

	/** Convenience: send event with a single string param. */
	void send(const Ogre::String &eventName, const Ogre::String &paramName,
		  const Ogre::String &value);

	/** Convenience: send event with a single int param. */
	void send(const Ogre::String &eventName, const Ogre::String &paramName,
		  int64_t value);

	/** Convenience: send event with a single float param. */
	void send(const Ogre::String &eventName, const Ogre::String &paramName,
		  float value);

	/** Convenience: send event with a single double param. */
	void send(const Ogre::String &eventName, const Ogre::String &paramName,
		  double value);

	/** Convenience: send event with a single entity ID param. */
	void send(const Ogre::String &eventName, const Ogre::String &paramName,
		  uint64_t entityId);

private:
	EventBus() = default;

	struct Listener {
		ListenerId id;
		Callback callback;
	};

	ListenerId m_nextId = 1;
	std::unordered_map<Ogre::String, std::vector<Listener> > m_listeners;
	std::unordered_map<ListenerId, Ogre::String> m_idToEvent;
};

#endif // EDITSCENE_EVENT_BUS_HPP
