#include "character_awareness.hpp"
#include "character_actor.hpp"
#include "utils/godot_macros.h"
#include <godot_cpp/variant/callable_method_pointer.hpp>

namespace godot {
void CharacterAwareness::_bind_methods() {
#define CLASSNAME CharacterAwareness
    GDSIGNAL("detect_actor", PropertyInfo(Variant::OBJECT, "character", PROPERTY_HINT_NODE_TYPE, "CharacterActor"));
    GDSIGNAL("lose_actor", PropertyInfo(Variant::OBJECT, "character", PROPERTY_HINT_NODE_TYPE, "CharacterActor"));
    GDSIGNAL("detect_node", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_NODE_TYPE, "Node"));
    GDSIGNAL("lose_node", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_NODE_TYPE, "Node"));
}

void CharacterAwareness::_enter_tree() {
    this->set_collision_mask(0x2);
}

void CharacterAwareness::_ready() {
    this->connect("body_entered", callable_mp(this, &CharacterAwareness::on_body_entered));
    this->connect("body_exited", callable_mp(this, &CharacterAwareness::on_body_exited));
}

void CharacterAwareness::on_body_entered(Node *node) {
    this->node_awareness.insert(node);
    this->emit_signal("detect_node", node);
    CharacterActor *actor = Object::cast_to<CharacterActor>(node);
    if(actor) {
        this->actor_awareness.insert(actor);
        this->emit_signal("detect_actor", actor);
    }
}

void CharacterAwareness::on_body_exited(Node *node) {
    this->node_awareness.erase(node);
    this->emit_signal("lose_node", node);
    CharacterActor *actor = Object::cast_to<CharacterActor>(node);
    if(actor) {
        this->actor_awareness.erase(actor);
        this->emit_signal("lose_actor", actor);
    }
}
}
