#include "global_world_state.hpp"
#include "character_actor.hpp"
#include "utils/game_root.hpp"
#include "utils/godot_macros.h"
#include <godot_cpp/variant/utility_functions.hpp>

namespace godot::goap {
void GlobalWorldState::_bind_methods() {
#define CLASSNAME GlobalWorldState
    GDFUNCTION(get_player_character);
}

bool GlobalWorldState::has_singleton() {
    return GlobalWorldState::singleton_instance != nullptr;
}

GlobalWorldState *GlobalWorldState::get_singleton() {
    return GlobalWorldState::singleton_instance;
}

void GlobalWorldState::_enter_tree() { GDGAMEONLY();
    if(GlobalWorldState::singleton_instance == nullptr) {
        GlobalWorldState::singleton_instance = this;
    }
}

void GlobalWorldState::_exit_tree() { GDGAMEONLY();
    if(GlobalWorldState::singleton_instance == this)
        GlobalWorldState::singleton_instance = nullptr;
}

void GlobalWorldState::_process(double delta_time) { GDGAMEONLY();
    global_state_cache.clear(); // invalidate cache
}

Vector3 GlobalWorldState::get_player_position() const {
    return this->get_player_character()->get_global_position();
}

CharacterActor *GlobalWorldState::get_player_character() const {
    return Ref<TunnelsGameMode>(GameRoot::get_singleton()->get_game_mode())->get_player_instance()->get_character();
}

Variant GlobalWorldState::get_world_property(StringName prop_key) {
    // check if prop key corresponds to a global key
    if(!prop_key.begins_with("g_"))
        return nullptr;
    // check if the key is cached for this frame
    else if(global_state_cache.has(prop_key))
        return global_state_cache.get(prop_key);
    // fetch by function name
    StringName const fn = "get_" + prop_key.erase(0, 2);
    if(this->has_method(fn)) {
        Variant result = this->call(fn);
        // cache and return
        this->global_state_cache.insert(prop_key, result);
        return result;
    } else {
#ifdef DEBUG_ENABLED_ENABLED
        abort();
#endif
        return nullptr;
    }
}

GlobalWorldState *GlobalWorldState::singleton_instance{nullptr};
}

