#include <client/Player.h>

#include <godot_cpp/classes/engine.hpp>
#include <godot_cpp/classes/input.hpp>
#include <godot_cpp/classes/input_map.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/variant/utility_functions.hpp>

static const float WalkSpeed = 2.0;
static const float RunSpeed = 7.0;
static const float JumpStrength = 15.0;
static const float Gravity = 50.0;

static const float LerpValue = 0.15;
static const float AnimationBlend = 7.0;

namespace blitz {

using namespace godot;

void Player::_bind_methods() {}

Player::Player() : m_PeerId(0) {
	// we set the player to an invalid position
	set_position({-99999, -999999, -999999});
}

Player::~Player() {}

void Player::_ready() {
	godot::InputMap::get_singleton()->load_from_project_settings();
	m_Mesh = Object::cast_to<godot::Node3D>(find_child("Mesh"));
	m_AnimationTree = Object::cast_to<godot::AnimationTree>(find_child("AnimationTree"));
	DEV_ASSERT(m_Mesh);
	DEV_ASSERT(m_AnimationTree);

	animate(0);
}

void Player::_physics_process(float delta) {
	if (godot::Engine::get_singleton()->is_editor_hint())
		return;

	move_and_slide();
	animate(delta);
}

void Player::animate(float delta) {
	if (is_on_floor()) {
		m_AnimationTree->set("parameters/ground_air_transition/transition_request", "grounded");

		float speed = get_velocity().length();

		if (speed > 0.2f) {
			if (speed >= RunSpeed) {
				m_AnimationTree->set("parameters/iwr_blend/blend_amount",
					godot::UtilityFunctions::lerp(
						m_AnimationTree->get("parameters/iwr_blend/blend_amount"), 1.0, delta * AnimationBlend));
			} else {
				m_AnimationTree->set("parameters/iwr_blend/blend_amount",
					godot::UtilityFunctions::lerp(
						m_AnimationTree->get("parameters/iwr_blend/blend_amount"), 0.0, delta * AnimationBlend));
			}
		} else {
			m_AnimationTree->set("parameters/iwr_blend/blend_amount",
				godot::UtilityFunctions::lerp(
					m_AnimationTree->get("parameters/iwr_blend/blend_amount"), -1.0, delta * AnimationBlend));
		}
	} else {
		m_AnimationTree->set("parameters/ground_air_transition/transition_request", "air");
	}
}

Vector3 Player::GetCameraRotation() const {
	return m_Mesh->get_rotation();
}

void Player::SetCameraRotation(const Vector3& a_Rotation) {
	m_Mesh->set_rotation(a_Rotation);
}

}  // namespace blitz
