#ifndef CHARACTER_MODULE_H_
#define CHARACTER_MODULE_H_
#include <flecs.h>
#include <nlohmann/json.hpp>
#include <Ogre.h>
#include "Components.h"
namespace ECS
{
struct Camera;
/* character */
struct Character {}; /* tag */
struct Player {}; /* tag */
struct CharacterGravity {};
struct CharacterBuoyancy {};
struct CharacterDisablePhysics {};
struct CharacterUpdatePhysicsState {};
struct Male {};
struct Female {};

struct CharacterBase {
	Ogre::String type;
    float mTimer;
	Ogre::Vector3 mBoneMotion;
	Ogre::Vector3 mBonePrevMotion;
	Ogre::Vector3 mGoalDirection; // actual intended direction in world-space
    bool is_submerged;
};
struct CharacterLocation {
	Ogre::Quaternion orientation;
	Ogre::Vector3 position;
};
struct CharacterInActuator {
	Ogre::String animationState;
    Vector3 prevMotion;
};
struct CharacterControlDisable {};
struct CharacterModule {
	CharacterModule(flecs::world &ecs);
	void updateCameraGoal(Camera &camera, Ogre::Real deltaYaw,
			      Ogre::Real deltaPitch, Ogre::Real deltaZoom);
    void createCharacter(flecs::entity e, const Ogre::Vector3 &position,
                 const Ogre::Quaternion &rotation,
                 const Ogre::String &faceModel,
                 const Ogre::String &hairModel,
                 const Ogre::String &topModel,
                 const Ogre::String &bottomModel,
                 const Ogre::String &feetModel);
    std::unordered_map<flecs::entity_t, Ogre::SceneNode *> characterNodes;
    std::unordered_map<flecs::entity_t, Ogre::Entity *>
        characterEntitiesFace;
    std::unordered_map<flecs::entity_t, Ogre::Entity *>
        characterEntitiesHair;
    std::unordered_map<flecs::entity_t, Ogre::Entity *> characterEntitiesTop;
    std::unordered_map<flecs::entity_t, Ogre::Entity *>
        characterEntitiesBottom;
    std::unordered_map<flecs::entity_t, Ogre::Entity *>
        characterEntitiesFeet;
    std::unordered_map<flecs::entity_t, Ogre::String> characterModelsFace;
    std::unordered_map<flecs::entity_t, Ogre::String> characterModelsHair;
    std::unordered_map<flecs::entity_t, Ogre::String> characterModelsTop;
    std::unordered_map<flecs::entity_t, Ogre::String> characterModelsBottom;
    std::unordered_map<flecs::entity_t, Ogre::String> characterModelsFeet;
    std::unordered_map<flecs::entity_t, Ogre::Vector3> characterPositions;
    std::unordered_map<flecs::entity_t, Ogre::Quaternion>
        characterOrientations;
    nlohmann::json body_parts;
    std::set<Ogre::String> mesh_names;
    void remapMeshToMasterSkeleton(Ogre::MeshPtr clothMesh,
                       Ogre::MeshPtr masterMesh);
    void getSlotMeshes(const Ogre::String &age, const Ogre::String &sex,
               const Ogre::String &slotName,
               std::vector<Ogre::String> &meshes);
    void preloadMeshes();
};
}
#endif
