#include "beam.hpp"
#include "utils/godot_macros.h"
#include <godot_cpp/classes/time.hpp>

namespace godot {
void Beam::_bind_methods() {
#define CLASSNAME Beam
}

void Beam::_enter_tree() { GDGAMEONLY();
    this->mesh_instance = this->get_node<MeshInstance3D>("MeshInstance3D");
    if(this->mesh_instance) {
        this->mesh = this->mesh_instance->get_mesh()->duplicate();
        this->mesh_instance->set_mesh(this->mesh);
    }
    this->collision_shape = this->get_node<CollisionShape3D>("CollisionShape3D");
    if(this->collision_shape) {
        this->shape = this->collision_shape->get_shape()->duplicate();
        this->collision_shape->set_shape(shape);
    }
    this->connect("body_entered", callable_mp(this, &Beam::body_entered));
}

void Beam::_process(double delta_time) { GDGAMEONLY();
    if(this->end_time != 0.f && Time::get_singleton()->get_ticks_msec() / 1000.f > this->end_time) {
        this->queue_free();
    }
}

void Beam::body_entered(Node3D *node) {
    node->call("damage");
}

void Beam::set_from_to(Vector3 from, Vector3 to) {
    Vector3 const z = (to - from).normalized();
    Vector3 const x = z.cross({0.f, 1.f, 0.f}).normalized();
    double const length = (from - to).length();

    this->set_global_position(from + z * (length / 2.f + 1.f));
    this->set_global_basis({x, z.cross(x).normalized(), z});
    if(this->mesh.is_valid())
        this->mesh->set_height(length);
    if(this->shape.is_valid())
        this->shape->set_height(length);
}

void Beam::set_end_time(float time_from_now) {
    this->end_time = Time::get_singleton()->get_ticks_msec() / 1000.f + time_from_now;
}
}
