#include "FreeCam.h"
#include "Utils/ImGuiRenderUtils.h"
#include "Utils/ColorUtils.h"
#include "Utils/MoveUtils.h"

auto FreeCam::onImGuiRender() -> void {
	if (Client::screenName != _("hud_screen")) return;

	if (!enabled) return;

	auto clientinstance = Client::clientinstance;
	if (!clientinstance) return;

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

	auto aabbshapecomponent = localplayer->getAABBShapeComponent();
	if (!aabbshapecomponent) return;
	
	Utils::ImGuiRender::setDrawList(ImGui::GetBackgroundDrawList());
	Utils::ImGuiRender::setColor(Utils::Color::getColor(3.f, 0, 0.2f));
	Utils::ImGuiRender::setSecondColor(Utils::Color::getColor(3.f, 0, 1.f));
	Utils::ImGuiRender::setThickness(1.f);

	Utils::ImGuiRender::fillBox(savedLow, savedHigh);
}

auto FreeCam::onEnabled() -> void {
	auto clientinstance = Client::clientinstance;
	if (!clientinstance) return;

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

	auto aabbshapecomponent = localplayer->getAABBShapeComponent();
	if (!aabbshapecomponent) return;

	savedLow = aabbshapecomponent->mAABB.min;
	savedHigh = aabbshapecomponent->mAABB.max;
	savedPos = Utils::Move::getPosition(localplayer);
	savedPos2 = Utils::Move::getBlockPosition(localplayer);

	saved = true;
}

auto FreeCam::onDisabled() -> void {
	if (!saved) return;

	auto clientinstance = Client::clientinstance;
	if (!clientinstance) return;

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

	if (queueDisable) return;

	Utils::Move::setVelocity(localplayer, glm::vec3(0, 0, 0));
	Utils::Move::setPosition(localplayer, savedPos);
	Utils::Move::teleportPosition(localplayer, savedPos2);
	saved = false;
}

auto FreeCam::onWorldTick(Player* _this) -> void {
	if (!enabled) return;

	auto clientinstance = Client::clientinstance;
	if (!clientinstance) return;

	auto minecraft = clientinstance->getMinecraft();
	if (!minecraft) return;

	auto actorrotationcomponent = _this->getActorRotationComponent();
	if (!actorrotationcomponent) return;

	float angle = (actorrotationcomponent->mRotationDegree.y + 90) * (3.1415927f / 180);
	float yaw = Utils::Move::getMoveYaw() + actorrotationcomponent->mRotationDegree.y;

	glm::vec3 velocity = Utils::Move::getVelocity(_this);
	glm::vec3 position = Utils::Move::getPosition(_this);

	velocity.y = 0.f;

	if (Client::screenName == _("hud_screen")) {
		if (Utils::Move::isSneaking())
			velocity.y = -speed;
		else if (Utils::Move::isJumping())
			velocity.y = speed;

		if (Utils::Move::isForwarding()) {
			velocity.x = cos(angle) * speed;
			velocity.z = sin(angle) * speed;
		}


		if (Utils::Move::isMoving()) {
			velocity.x = cos(yaw * (3.1415927f / 180)) * speed;
			velocity.z = sin(yaw * (3.1415927f / 180)) * speed;
		}
		else if (!Utils::Move::isJumping() && !Utils::Move::isSneaking()) {
			velocity = glm::vec3();
		}
	}

	Utils::Move::setVelocity(_this, velocity);
}

auto FreeCam::onPacketSendAfter(Packet* packet, bool* cancel) -> void {
	static bool resetpos = false;

	if (queueDisable) return;

	if (packet->getID() == PacketID::PlayerAuthInput) {
		auto playerauthinput = reinterpret_cast<PlayerAuthInputPacket*>(packet);

		if (enabled) {
			*cancel = true;

			resetpos = false;
		}
		else if (!resetpos) {
			playerauthinput->setPos(savedPos);

			resetpos = true;
		}
	}
}

auto FreeCam::onDimensionChanged() -> void {
	queueDisable = true;
}

auto FreeCam::onClient() -> void {
	static bool checkstart = false;

	if (queueDisable) {
		if (!checkstart) {
			if (Client::screenName != _("hud_screen")) {
				checkstart = true;
			}
		}
		
		if (checkstart) {
			if (Client::screenName == _("hud_screen")) {
				
				if (enabled) {
					for (Mod* mod : Client::modlist) {
						if (!mod->enabled && mod->onlyenabled) continue;

						mod->onAnyDisabled();
					}
					enabled = false;
					onDisabled();
				}
				queueDisable = false;
			}
		}
	}
	else {
		checkstart = false;
	}
}

auto FreeCam::getMode() -> std::string {
	return _("Cancel");
}
