#include <server/ServerWorld.h>

#include <blitz/godot/NetworkInterface.h>
#include <client/Player.h>
#include <godot_cpp/classes/engine.hpp>
#include <godot_cpp/variant/utility_functions.hpp>

namespace blitz {

using namespace godot;

void ServerWorld::_bind_methods() {}

ServerWorld::ServerWorld() {}

ServerWorld::~ServerWorld() {}

void ServerWorld::_process(float delta) {
#if DEBUG_ENABLED
	if (Engine::get_singleton()->is_editor_hint())
		return;
#endif
	m_PassedTime += delta;
	if (m_PassedTime < 0.05f)
		return;

	m_PassedTime = 0.0f;
	SyncPlayersPos();
}

void ServerWorld::SyncPlayersPos() {
	for (int i = 0; i < m_Players->get_child_count(); i++) {
		Player* player = Object::cast_to<Player>(m_Players->get_child(i));
		DEV_ASSERT(player);
		m_NetworkInterface->BroadcastPacket(protocol::packets::PlayerPositionAndRotation(
			{player->GetId(), player->get_position(), player->GetCameraRotation(), player->get_velocity()}));
	}
}

void ServerWorld::HandlePacket(const protocol::packets::PlayerPositionAndRotation& a_PlayerPos) {
	const auto& data = a_PlayerPos.m_Data;
	if (data.m_Player != a_PlayerPos.m_Sender)
		return;

	Player* player = GetPlayerById(data.m_Player);
	if (!player)
		return;

	if ((data.m_Position - player->get_position()).length() > 10) {
		UtilityFunctions::print(
			"Player ", data.m_Player, " moved too fast ! (from ", player->get_position(), " to ", data.m_Position, ")");
		return;
	}

	SetPlayerPositionAndRotation(data.m_Player, data.m_Position, data.m_Rotation, data.m_Velocity);
}

void ServerWorld::AddPlayer(PlayerID a_PlayerId, godot::String a_PlayerName) {
	World::AddPlayer(a_PlayerId, a_PlayerName);
	Player* player = GetPlayerById(a_PlayerId);
	player->set_position({0, 0, 0});
}

}  // namespace blitz