#ifndef DRONE_HPP
#define DRONE_HPP

#include "car_player.hpp"
#include "godot_cpp/classes/animation_player.hpp"
#include "godot_cpp/classes/navigation_agent3d.hpp"
#include "godot_cpp/classes/packed_scene.hpp"
#include <godot_cpp/classes/node3d.hpp>

namespace godot {
//! State of a drone
enum class DroneState {
    //! Chase the player
    CHASE,
    //! Stop, drop, and explode
    DROP,
    //! Go anywhere but where the player is
    FLEE
};

//! An enemy drone, moves around using navigation. Model is expected to float well above the transform origin.
class Drone : public Node3D {
    GDCLASS(Drone, Node3D);
    //! Register properties
    static void _bind_methods();
public:
    //! Get required object references and connect observers.
    virtual void _ready() override;
    //! Update the state machine.
    virtual void _process(double delta_time) override;
    //! Process the chase state. Navigate ahead of player player and drop when near target.
    void process_chase(double delta_time);
    //! Flee state, Flee away from the player.
    void process_flee(double delta_time);
    //! Navigate according to path.
    void process_navigate(double delta_time);
    //! Recalculate pathing based on current state.
    void recalculate_navigation();
    //! Spawn an explosion after dropping.
    void spawn_explosion();
    //! Listener for when a key is found, to up the difficulty.
    void key_found(int total);

    //! Listener for when the player grabs a turret pickup.
    void start_flee();
    //! Listener for when the player drop their turret pickup.
    void end_flee();

    //! The explosion to spawn after dropping.
    void set_explosion_scene(Ref<PackedScene> scene);
    //! The explosion to spawn after dropping.
    Ref<PackedScene> get_explosion_scene() const;
private:
    //! Time between pathing recalculations
    int recalc_frame_interval{10};
    //! Frame timer for next pathing recalculation
    int next_recalc{10};
    //! Movement speed in m/s
    float speed{30.f};
    //! How far ahead of the player to target
    float lead_time{2.f};
    //! distance at which to drop
    float target_distance{3.f};
    //! Current state machine state
    DroneState state{DroneState::CHASE};
    //! Target to chase / flee from
    CarPlayer *player{nullptr};
    //! Scene to spawn when exploding
    Ref<PackedScene> explosion_scene{};

    //! Navigation agent Component
    NavigationAgent3D *agent{nullptr};
    //! Animation player component
    AnimationPlayer *anim{nullptr};
};
}

#endif // !DRONE_HPP
