#include "MoveUtils.h"

#include "Mod/ClickGui.h"

#include "Utils/TimeUtils.h"

#include "Datas/LanguageDatas.h"

auto Utils::Move::isOnGround(Actor* _this) -> bool {
	auto statevectorcomponent = _this->getStateVectorComponent();
	if (!statevectorcomponent) return false;

	return statevectorcomponent->mPosDelta.y == -0.0784f;
}

auto Utils::Move::isOnGroundItem(Actor* _this) -> bool {
	auto statevectorcomponent = _this->getStateVectorComponent();
	if (!statevectorcomponent) return false;

	return statevectorcomponent->mPosDelta.y == 0.f;
}

auto Utils::Move::isStoping(Player* _this) -> bool {
	auto statevectorcomponent = _this->getStateVectorComponent();
	if (!statevectorcomponent) return false;

	return !(statevectorcomponent->mPosDelta.x == 0.f ||
		statevectorcomponent->mPosDelta.y == 0.f ||
		statevectorcomponent->mPosDelta.z == 0.f
		);
}

auto Utils::Move::isMoving() -> bool {
	if (Client::findMod<ClickGui>(Datas::Language::get().module.render.clickgui.name.c_str()) && Client::findMod<ClickGui>(Datas::Language::get().module.render.clickgui.name.c_str())->enabled) return false;

	return Client::keymaps[Client::optleft] || Client::keymaps[Client::optright] || Client::keymaps[Client::optback] || Client::keymaps[Client::optforward];
}

auto Utils::Move::isSneaking() -> bool {
	return Client::keymaps[Client::optsneak];
}

auto Utils::Move::isSneaking2(Player* _this) -> bool {
	auto moveinputcomponent = _this->getMoveInputComponent();
	if (!moveinputcomponent) return false;

	return moveinputcomponent->mSneaking;
}

auto Utils::Move::isJumping() -> bool {
	return Client::keymaps[Client::optjump];
}

auto Utils::Move::setJumping(Player* _this, bool state) -> void {
	auto moveinputcomponent = _this->getMoveInputComponent();
	if (!moveinputcomponent) return;

	moveinputcomponent->mJumping = state;
	moveinputcomponent->mInputState.mJumpDown = state;
	moveinputcomponent->mRawInputState.mJumpDown = state;
}
	
auto Utils::Move::isJumping2(Player* _this) -> bool {
	auto moveinputcomponent = _this->getMoveInputComponent();
	if (!moveinputcomponent) return false;

	return moveinputcomponent->mJumping;
}
	
auto Utils::Move::setSprinting(Player* _this, bool state) -> void {
	auto moveinputcomponent = _this->getMoveInputComponent();
	if (!moveinputcomponent) return;

	moveinputcomponent->mSprinting = state;
	moveinputcomponent->mInputState.mSprintDown = state;
	moveinputcomponent->mRawInputState.mSprintDown = state;
}

auto Utils::Move::setSprinting2(Player* _this, bool state) -> void {
	_this->setSprinting(state);
}

auto Utils::Move::isForwarding() -> bool {
	return Client::keymaps[Client::optforward];
}

auto Utils::Move::isWalking(Player* _this) -> bool {
	auto moveinputcomponent = _this->getMoveInputComponent();
	if (!moveinputcomponent) return false;

	return moveinputcomponent->mInputState.mUp;
}

auto Utils::Move::isBacking(Player* _this) -> bool {
	auto moveinputcomponent = _this->getMoveInputComponent();
	if (!moveinputcomponent) return false;

	return moveinputcomponent->mInputState.mDown;
}

auto Utils::Move::isLefting(Player* _this) -> bool {
	auto moveinputcomponent = _this->getMoveInputComponent();
	if (!moveinputcomponent) return false;

	return moveinputcomponent->mInputState.mLeft;
}

auto Utils::Move::isRighting(Player* _this) -> bool {
	auto moveinputcomponent = _this->getMoveInputComponent();
	if (!moveinputcomponent) return false;

	return moveinputcomponent->mInputState.mRight;
}

auto Utils::Move::isHorizontal(Player* _this) -> bool {
	glm::vec3 vel = Utils::Move::getVelocity(_this);
	if (vel.x != 0.f && vel.z != 0.f) {
		return false;
	}

	if (Utils::Move::isWalking(_this) ||
		Utils::Move::isBacking(_this) ||
		Utils::Move::isLefting(_this) ||
		Utils::Move::isRighting(_this)
		)
	{
		return true;
	}
	return false;
}

auto Utils::Move::setVelocity(Player* _this, glm::vec3 velocity) -> void {
	_this->getStateVectorComponent()->mPosDelta = velocity;
}

auto Utils::Move::getPosition(Player* _this) -> glm::vec3 {
	glm::vec3 pos = _this->getStateVectorComponent()->mPos;
	return pos;
}

auto Utils::Move::getPositionEntity(Actor* _this) -> glm::vec3 {
	glm::vec3 pos = _this->getStateVectorComponent()->mPos;
	return pos;
}

auto Utils::Move::getTopPosition(Player* _this) -> glm::vec3 {
	glm::vec3 pos = _this->getAABBShapeComponent()->mAABB.max;
	return pos;
}

auto Utils::Move::getEyePosition(Player* _this) -> glm::vec3 {
	glm::vec3 pos = _this->getAABBShapeComponent()->mAABB.max;
	pos.y -= 0.1f;
	return pos;
}

auto Utils::Move::setPosition(Player* _this, glm::vec3 position) -> void {
	_this->getStateVectorComponent()->mPos = position;
	_this->getStateVectorComponent()->mPosPrev = position;
}

auto Utils::Move::teleportPosition(Player* _this, glm::vec3 position) -> void {
	_this->teleportTo(position);
}

auto Utils::Move::getPrevPosition(Player* _this) -> glm::vec3 {
	glm::vec3 pos = _this->getStateVectorComponent()->mPosPrev;
	return pos;
}

auto Utils::Move::getBlockPosition(Player* _this) -> glm::vec3 {
	if (!_this) return glm::vec3();

	glm::vec3 pos;
	auto statevectorcomponent = _this->getStateVectorComponent();
	auto aabbshapecomponent = _this->getAABBShapeComponent();
	if (statevectorcomponent && aabbshapecomponent) {
		pos = statevectorcomponent->mPos;
		pos.y = (int)aabbshapecomponent->mAABB.min.y;
	}
	return pos;
}

auto Utils::Move::getVelocity(Player* _this) -> glm::vec3 {
	return _this->getStateVectorComponent()->mPosDelta;
}

auto Utils::Move::getSpeed(Player* _this) -> float {
	glm::vec3 from = getPrevPosition(_this);
	from.y = 0;
	glm::vec3 to = getPosition(_this);
	to.y = 0;

	return Utils::Math::getDistance(from, to);
}

auto Utils::Move::getMoveYaw() -> float {
	float yaw = 0.f;
	if (Client::keymaps[Client::optforward]) {
		if (!Client::keymaps[Client::optleft] && !Client::keymaps[Client::optright])
			yaw += 90.f;
		else if (Client::keymaps[Client::optleft])
			yaw += 45.f;
		else if (Client::keymaps[Client::optright])
			yaw += 135.f;
	}
	else if (Client::keymaps[Client::optback]) {
		if (!Client::keymaps[Client::optleft] && !Client::keymaps[Client::optright])
			yaw -= 90.f;
		else if (Client::keymaps[Client::optleft])
			yaw -= 45.f;
		else if (Client::keymaps[Client::optright])
			yaw -= 135.f;
	}
	else if (!Client::keymaps[Client::optforward] && !Client::keymaps[Client::optback]) {
		if (!Client::keymaps[Client::optleft] && Client::keymaps[Client::optright])
			yaw += 180.f;
	}

	if (Client::keymaps[Client::optforward] && Client::keymaps[Client::optback])
		yaw -= 90.f;

	return yaw;
}
