#ifndef EDITSCENE_COMPONENTREGISTRATION_HPP
#define EDITSCENE_COMPONENTREGISTRATION_HPP
#pragma once

#include "ComponentRegistry.hpp"
#include <OgreSceneManager.h>
#include <flecs.h>
#include <functional>

// Forward declarations
class EditorPhysicsSystem;

namespace Ogre {
	class RenderWindow;
}

/**
 * Helper class to modularize component registration
 * Each component module registers itself using static initialization
 */
class ComponentRegistration {
public:
	using RegistrationFunc = std::function<void(ComponentRegistry&, 
	                                            Ogre::SceneManager*,
	                                            EditorPhysicsSystem*,
	                                            Ogre::RenderWindow*)>;

	/**
	 * Register a component module
	 * Call this from a .cpp file to auto-register the component
	 */
	static void registerComponent(RegistrationFunc func);

	/**
	 * Register all components with the registry
	 * Call this once during editor initialization
	 */
	static void registerAll(ComponentRegistry& registry,
	                        Ogre::SceneManager* sceneMgr,
	                        EditorPhysicsSystem* physicsSystem,
	                        Ogre::RenderWindow* renderWindow = nullptr);

private:
	static std::vector<RegistrationFunc>& getRegistrants();
};

/**
 * Macro to simplify component registration
 * Usage in a .cpp file:
 * 
 *   REGISTER_COMPONENT("My Component", MyComponent, MyComponentEditor)
 *   {
 *       // Adder
 *       registry.registerComponent<MyComponent>(
 *           name, std::make_unique<MyComponentEditor>(...),
 *           [](flecs::entity e) { ... },
 *           [](flecs::entity e) { ... });
 *   }
 * 
 * Or with a group:
 *   REGISTER_COMPONENT_GROUP("My Component", "Group Name", MyComponent, MyComponentEditor)
 *   {
 *       registry.registerComponent<MyComponent>(
 *           name, group, std::make_unique<MyComponentEditor>(...),
 *           [](flecs::entity e) { ... },
 *           [](flecs::entity e) { ... });
 *   }
 */
#define REGISTER_COMPONENT(nameStr, ComponentType, EditorType) \
    REGISTER_COMPONENT_GROUP(nameStr, "Miscellaneous", ComponentType, EditorType)

#define REGISTER_COMPONENT_GROUP(nameStr, groupStr, ComponentType, EditorType) \
    static const char* ComponentType##_name = nameStr; \
    static const char* ComponentType##_group = groupStr; \
    static void register_##ComponentType(ComponentRegistry& registry, \
                                         Ogre::SceneManager* sceneMgr, \
                                         EditorPhysicsSystem* physics, \
                                         Ogre::RenderWindow* renderWindow); \
    struct ComponentType##_registrar { \
        ComponentType##_registrar() { \
            ComponentRegistration::registerComponent(register_##ComponentType); \
        } \
    } static ComponentType##_instance; \
    static void register_##ComponentType(ComponentRegistry& registry, \
                                         Ogre::SceneManager* sceneMgr, \
                                         EditorPhysicsSystem* physics, \
                                         Ogre::RenderWindow* renderWindow)

/**
 * Helper for standard SceneNode-attached components
 */
template<typename T>
struct SceneNodeComponentTraits {
	// Override these for your component type
	static const char* getName() { return "Component"; }
	static void onAdd(T& comp, Ogre::SceneNode* node) {}
	static void onRemove(T& comp, Ogre::SceneNode* node) {}
	static void onUpdate(T& comp) {}
};

#endif // EDITSCENE_COMPONENTREGISTRATION_HPP
