#include "Players.h"

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

#include "Mod/Animations.h"

auto Hooks::Players::callback_interpolatedheadyaw(Player* _this, float a1) -> float {
	float original = player_interpolatedheadyaw(_this, a1);
	for (Mod* mod : Client::modlist) {
		if (!mod->enabled && mod->onlyenabled) continue;

		mod->onInterpolatedHeadYaw(_this, &original);
	}
	
	return original;
}

auto Hooks::Players::callback_interpolatedbodyyaw(Player* _this, float a1) -> float {
	float original = player_interpolatedbodyyaw(_this, a1);

	for (Mod* mod : Client::modlist) {
		if (!mod->enabled && mod->onlyenabled) continue;

		mod->onInterpolatedBodyYaw(_this, &original);
	}
	
	return original;
}

auto Hooks::Players::callback_basetick(Player* _this) -> void {
	for (Mod* mod : Client::modlist) {
		if (!mod->enabled && mod->onlyenabled) continue;

		mod->onBaseTick(_this);
	}

	player_basetick(_this);
}

auto Hooks::Players::callback_getshadowradius(Player* _this) -> float {
	float original = player_getshadowradius(_this);

	for (Mod* mod : Client::modlist) {
		if (!mod->enabled && mod->onlyenabled) continue;

		mod->onGetShadowRadius(_this, &original);
	}

	return original;
}

auto Hooks::Players::callback_isonfire(Player* _this) -> bool {
	bool isonfire = player_isonfire(_this);

	for (Mod* mod : Client::modlist) {
		if (!mod->enabled && mod->onlyenabled) continue;

		mod->onFire(_this, &isonfire);
	}

	return isonfire;
}

auto Hooks::Players::callback_swing(Player* _this) -> void {
	bool cancel = false;
	for (Mod* mod : Client::modlist) {
		if (!mod->enabled && mod->onlyenabled) continue;

		mod->onSwing(_this, &cancel);
	}

	if (!cancel)
		player_swing(_this);
}

auto Hooks::Players::callback_worldtick(Player* _this) -> void {
	if (_this->getPlayerInventory()->getInventory()->getItemStack(_this->getPlayerInventory()->getSelectedSlot()))
		_this->getPlayerInventory()->setHandSlot(_this->getPlayerInventory()->getSelectedSlot());
	
	for (Mod* mod : Client::modlist) {
		if (!mod->enabled && mod->onlyenabled) continue;

		mod->onWorldTick(_this);
	}

	{
		auto actorwalkanimationcomponent = _this->getActorWalkAnimationComponent();
		if (actorwalkanimationcomponent) {
			auto animationsMod = Client::findMod<Animations>(_("Animations"));
			if (Utils::Move::isJumping2(_this) && (animationsMod->enabled && animationsMod->javamotion)) {
				actorwalkanimationcomponent->mWalkAnimSpeedMultiplier = 3.f;
			}
			else {
				actorwalkanimationcomponent->mWalkAnimSpeedMultiplier = 1.f;
			}
		}
	}

	{
		if (Client::fling) {
			Utils::Move::setVelocity(_this, glm::ivec3(0.f, 5.f, 0.f));
			Client::fling = false;
		}
	}

	{
		auto it = std::find_if(Client::attackdatas.rbegin(), Client::attackdatas.rend(), [](const Client::AttackData& data) {
			return Utils::Time::getMs() - data.start >= 1000.f;
			});
	}

	player_worldtick(_this);
}
