#include "CheatDetector.h"

#include "Utils/PlayerUtils.h"
#include "Utils/MoveUtils.h"
#include "Utils/ChatUtils.h"

auto CheatDetector::onWorldTick(Player* _this) -> void {
	name = Datas::Language::get().module.other.cheatdetector.name;
	description = Datas::Language::get().module.other.cheatdetector.description;

	if (!enabled) return;

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

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

	auto level = localplayer->getLevel();
	if (!level) return;

	level->forEachPlayer([&](Player& player) {

		if (Utils::Players::isRealPlayer(&player)) {
			std::string name = (&player)->getNameTag();
			if (name.empty()) return true;

			glm::vec3 velocity = Utils::Move::getVelocity(&player);
			float speed = Utils::Move::getSpeed(&player);

			DetectData datas;
			datas.type = DetectData::DetectType::NONE;
			datas.name = name;
			datas.alerted = false;

			if (player.getHurtTime() == 10) {
				if (velocity.y == 0.f) {
					datas.type = DetectData::DetectType::VelocityCancel;
					datas.level = DetectData::DetectLevel::A;
				}
				else if (velocity.y < 0.1f && velocity.y > 0.f) {
					datas.type = DetectData::DetectType::VelocityCancel;
					datas.level = DetectData::DetectLevel::B;
				}
				else if (velocity.y < 0.2f && velocity.y > 0.1f) {
					datas.type = DetectData::DetectType::VelocityCancel;
					datas.level = DetectData::DetectLevel::C;
				}
				else if (velocity.y < 0.3f && velocity.y > 0.2f) {
					datas.type = DetectData::DetectType::VelocityCancel;
					datas.level = DetectData::DetectLevel::D;
				}
			}

			if (datas.type == DetectData::DetectType::NONE) {
				if (velocity.y == 0.f) {
					if (speed > 0.91f) {
						datas.type = DetectData::DetectType::Fly;
						datas.level = DetectData::DetectLevel::A;
					}
					else if (speed > 0.91f) {
						datas.type = DetectData::DetectType::Fly;
						datas.level = DetectData::DetectLevel::B;
					}
					else if (speed > 0.9f) {
						datas.type = DetectData::DetectType::Fly;
						datas.level = DetectData::DetectLevel::C;
					}
					else if (speed > 0.6f) {
						datas.type = DetectData::DetectType::Fly;
						datas.level = DetectData::DetectLevel::D;
					}
				}
			}

			if (datas.type == DetectData::DetectType::NONE) {
				if (speed > 2.4f) {
					datas.type = DetectData::DetectType::Speed;
					datas.level = DetectData::DetectLevel::A;
				}
				else if (speed > 1.9f) {
					datas.type = DetectData::DetectType::Speed;
					datas.level = DetectData::DetectLevel::B;
				}
				else if (speed > 1.4f) {
					datas.type = DetectData::DetectType::Speed;
					datas.level = DetectData::DetectLevel::C;
				}
				else if (speed > 1.2f) {
					datas.type = DetectData::DetectType::Speed;
					datas.level = DetectData::DetectLevel::D;
				}
			}


			if (datas.type != DetectData::DetectType::NONE)
				detectdatas.push_back(datas);
		}

		return true;
		});

	for (DetectData detectdata : detectdatas) {
		std::string detecttype = _("");
		switch (detectdata.type) {
		case DetectData::DetectType::VelocityCancel:
			detecttype = _("VelocityCancel");
			break;
		case DetectData::DetectType::Speed:
			detecttype = _("Speed");
			break;
		case DetectData::DetectType::Fly:
			detecttype = _("Fly");
			break;
		case DetectData::DetectType::NONE:
		default:
			detecttype = _("Unknown");
			break;
		}

		std::string detectlevel = _("");
		switch (detectdata.type) {
		case DetectData::DetectLevel::A:
			detectlevel = _("A");
			break;
		case DetectData::DetectLevel::B:
			detectlevel = _("B");
			break;
		case DetectData::DetectLevel::C:
			detectlevel = _("C");
			break;
		case DetectData::DetectLevel::D:
			detectlevel = _("D");
			break;
		default:
			detectlevel = _("?");
			break;
		}

		Utils::Chat::display(Utils::String::removeToEscape(Utils::String::removeSymbols(detectdata.name)) + " has failed " + detecttype + _("-") + detectlevel);
	}
	detectdatas.clear();
}
