#ifndef TURRET_HPP
#define TURRET_HPP

#include <godot_cpp/classes/area3d.hpp>
#include <godot_cpp/classes/packed_scene.hpp>
#include <godot_cpp/classes/rigid_body3d.hpp>
#include <godot_cpp/templates/hash_set.hpp>
#include <godot_cpp/templates/vector.hpp>

namespace godot {
enum class TurretState {
    WAITING = 0x0,
    LOCKING = 0x1,
    CHARGING,
    FIRING
};
class Turret : public RigidBody3D {
    GDCLASS(Turret, RigidBody3D);
    static void _bind_methods();
public:
    virtual void _enter_tree() override;
    virtual void _process(double delta_time) override;

    void awareness_changed();
    Node3D *select_target();

    void lead_target(double delta_time);

    void detect_node(Node3D *node);
    void lose_node(Node3D *node);
    void try_next_state();
    void create_beam();


    void beam_ended();

    void set_fire_time(float val);
    float get_fire_time() const;
    void set_charge_time(float val);
    float get_charge_time() const;
    void set_lock_time(float val);
    float get_lock_time() const;

    void set_invert_targets(bool value);
    void set_attack_classes(Array array);
    Array get_attack_classes() const;
    void set_beam_scene(Ref<PackedScene> scene);
    Ref<PackedScene> get_beam_scene() const;
private:
    Node3D *current_target{nullptr};
    bool invert_attack_classes{false};
    Vector3 aim_position{0.f, 0.f, 0.f};
    Vector3 last_target_position{0.f, 0.f, 0.f};
    float last_state_switch{0.f};
    float lead_distance{1.2f};

    Node3D *gun_node{nullptr};
    Vector3 gun_node_offset{0.f, 0.f, 0.f};

    TurretState state{TurretState::WAITING};

    Vector<StringName> attack_classes{};
    HashSet<Node3D*> awareness{};

    Ref<PackedScene> beam_scene{};

    float fire_time{1.0f};
    float charge_time{1.f};
    float lock_time{1.3f};
};
}

#endif // !TURRET_HPP
