#ifndef GOAP_ACTION_DB_HPP
#define GOAP_ACTION_DB_HPP

#include "action.hpp"

namespace goap {
/*! Global access to all (registered) Action types.
 *
 * Register them with the `register_action` function from `initialize_gdextension_types()`.
 * To represent an Action in the editor, the getter and setter should act as if the property is an int.
 * The property should then be registered as an enum with `get_enum_hint()` as hint.
 * Inside the getter, `Action->get_id()` can be returned. While the setter assigns the underlying value to `ActionDB::get_action(id)`.
 * ```
 * void Example::set_action(int id) {
 *      this->action = ActionDB::get_action(id);
 * }
 * int Example::get_action() const {
 *      return this->action->get_id();
 * }
 * ```
 */
class ActionDB {
    struct StaticData {
        StaticData() = default;
        ~StaticData();
        gd::String &get_hint();
        gd::String &get_array_hint();
        gd::String *hint{nullptr};
        gd::String *array_hint{nullptr};
        gd::Vector<Action *> actions{};
    };
    static ActionID register_action(Action *instance, gd::String name);
public:
    /*! Get action by ID.
     */
    static Action const *get_action(ActionID id);
    /*! Get the csv godot enum hint.
     */
    static gd::String const &get_enum_hint();
    static gd::String const &get_array_hint();
    /*! Add action to database.
     *
     * \returns Action's assigned ID.
     */
    template<class TAction>
    _FORCE_INLINE_ static ActionID register_action() {
        return ActionDB::register_action(new TAction(), TAction::get_static_class());
    }
private:
    static StaticData data;
};
}

#endif // !GOAP_ACTION_DB_HPP
