#include "ServerRotations.h"
#include "Client.h"
#include "Utils/MathUtils.h"

auto ServerRotations::onViewPerspectiveAfter(int* perspective) -> void {
	perspective_ = *perspective;
}

auto ServerRotations::onRenderActorBefore(Actor* _this, glm::vec3* camera, glm::vec3* position) -> void {
	auto clientinstance = Client::clientinstance;
	if (!clientinstance) return;

	auto localplayer = clientinstance->getLocalPlayer();
	if (!localplayer) return;

	if (_this != localplayer) return;

	static float pitch_;

	if (!whenfirst && perspective_ == 0) return;

	pitch_ = Utils::Math::lerp(pitch_, _pitch, Client::deltaTime * headspeed);

	if (perspective_ == 0) return;

	mRotationDegree = _this->getActorRotationComponent()->mRotationDegree;
	mRotationDegreePrevious = _this->getActorRotationComponent()->mRotationDegreePrevious;

	_this->getActorRotationComponent()->mRotationDegree.x = pitch_;
	_this->getActorRotationComponent()->mRotationDegreePrevious.x = pitch_;
}

auto ServerRotations::onRenderActorAfter(Actor* _this) -> void {
	auto clientinstance = Client::clientinstance;
	if (!clientinstance) return;

	auto localplayer = clientinstance->getLocalPlayer();
	if (!localplayer) return;

	if (_this != localplayer) return;
	if (perspective_ == 0) return;

	_this->getActorRotationComponent()->mRotationDegreePrevious.x = mRotationDegreePrevious.x;
	_this->getActorRotationComponent()->mRotationDegree.x = mRotationDegree.x;
}

auto ServerRotations::onInterpolatedHeadYaw(Player* _this, float* yaw) -> void {
	auto clientinstance = Client::clientinstance;
	if (!clientinstance) return;

	auto localplayer = clientinstance->getLocalPlayer();
	if (!localplayer) return;

	if (_this != localplayer) return;

	static float yaw_;

	if (!whenfirst && perspective_ == 0) return;

	yaw_ = Utils::Math::wrap(yaw_, _headyaw - 180.f, _headyaw + 180.f);
	yaw_ = Utils::Math::lerp(yaw_, _headyaw, Client::deltaTime * headspeed);

	if (perspective_ == 0) return;

	*yaw = yaw_;
}

auto ServerRotations::onInterpolatedBodyYaw(Player* _this, float* yaw) -> void {
	auto clientinstance = Client::clientinstance;
	if (!clientinstance) return;

	auto localplayer = clientinstance->getLocalPlayer();
	if (!localplayer) return;

	if (_this != localplayer) return;

	static float yaw_;

	if (!whenfirst && perspective_ == 0) return;

	yaw_ = Utils::Math::wrap(yaw_, _yaw - 180.f, _yaw + 180.f);
	yaw_ = Utils::Math::lerp(yaw_, _yaw, Client::deltaTime * bodyspeed);

	if (!bodylock && !changedrot) {
		return;
	}

	if (perspective_ == 0) return;

	*yaw = yaw_;
}


auto ServerRotations::onPacketSendBefore2(Packet* packet) -> void {
	if (packet->getID() == PacketID::PlayerAuthInput) {
		PlayerAuthInputPacket* playerauthinput = reinterpret_cast<PlayerAuthInputPacket*>(packet);
		__pitch = playerauthinput->getPitch();
		__yaw = playerauthinput->getYaw();
		__headyaw = playerauthinput->getHeadYaw();
	}
}

auto ServerRotations::onPacketSendAfter(Packet* packet, bool* cancel) -> void {
	if (packet->getID() == PacketID::PlayerAuthInput) {
		PlayerAuthInputPacket* playerauthinput = reinterpret_cast<PlayerAuthInputPacket*>(packet);
		_pitch = playerauthinput->getPitch();
		_yaw = playerauthinput->getYaw();
		_headyaw = playerauthinput->getHeadYaw();

		if (_pitch != __pitch ||
			_yaw != __yaw ||
			_headyaw != __headyaw
			) changedrot = true;
		else
			changedrot = false;
	}
}

auto ServerRotations::getMode() -> std::string {
	std::stringstream ss;
	ss.precision(1);
	ss << std::fixed << headspeed << _(" ") << bodyspeed;

	return ss.str();
}
