#include <scene/main/node.h>
#include <core/math/vector3.h>
#include <modules/detour/navmesh_query.h>

class Spatial;
class DetourNavigationQuery;
class DetourCrowdManager;
class ImmediateGeometry;
class PhysicsBody;
class AnimationTree;
class SmartObjectManager;

class Characters_: public Node {
	GDCLASS(Characters_, Node)
public:
	Characters_();
	~Characters_();
	void walkto(const Node *ch, const Vector3 &target);
	void walkto_node(const Node *ch, const Node *target);
	void walkto_agent(Node *ch, const Vector3 &target);
	void walkto_agent_node(Node *ch, const Node *target);
	void set_navmesh(Ref<DetourNavigationMesh> mesh, const Transform &xform);
	float forward_probe(Node *body, float lookahead,
			float start_height, float end_height,
			float height_step);
	AnimationTree *get_animation_tree(const Node *npc) const;
	void animation_node_travel(Node *npc, const String &anim);
	void set_walk_speed(Node *npc, float speed, float strafe = 0.0f);
	float get_walk_speed(const Node *npc) const;
	String get_animation_node(const Node *npc);
	bool handle_cmdq(Node *npc);
	void character_physics(Object *obj);
	void rotate_to_agent(Spatial *obj);
	void speed_to_agent(Spatial *obj);
	void update_arrived(Object *obj);
	void set_crowd(DetourCrowdManager *crowd);
	void set_crowd_(Node *crowd_node);
	DetourCrowdManager *get_crowd() const;
	Object *get_crowd_();
	bool has_arrived(Object *obj);
	void agent_walk_stop(Object *obj);
	void set_root_motion_mod(const Transform &xform);
	Transform get_root_motion_mod() const;
	void load_body_parts(const String &path);
protected:
	void _notification(int p_what);
	static void _bind_methods();
	void process_character(Node *node, bool frozen);
	void process_frozen_character(Node *npc, const Vector3 &tposition);
	void process_normal_character(Node *npc, const Vector3 &tposition);
	HashMap<int, Vector3> static_targets;
	HashMap<int, int> dynamic_targets;
	HashMap<int, Vector<Vector3>> paths;
	DetourNavigationQuery *query;
	Ref<DetourNavigationQueryFilter> filter;
	SmartObjectManager *smm;

	bool initialized;
	ImmediateGeometry *debug;
	DetourCrowdManager *crowd;
	float arrive_precision;
	Transform root_motion_mod;
	bool no_navmesh;
	PoolVector<String> male_hairs;
	PoolVector<String> female_hairs;
	PoolVector<String> hair_materials;
	PoolVector<String> male_faces;
	PoolVector<String> female_faces;
	String scenes_path;
};

