#include "Actor.h"
#include "Utils/MemoryUtils.h"

auto Actor::getEntityContext() -> EntityContext& {
	return *reinterpret_cast<EntityContext*>((uintptr_t)this + 0x8);
}

auto Actor::getStateVectorComponent() -> StateVectorComponent* {
	if (Utils::File::getVersion() == _("1.21.80"))
		return *reinterpret_cast<StateVectorComponent**>((uintptr_t)this + 0x118 + (8 * 33));
	else if (Utils::File::getVersion() == _("1.21.73"))
		return *reinterpret_cast<StateVectorComponent**>((uintptr_t)this + 0x118 + (8 * 32));
	else if (Utils::File::getVersion() == _("1.21.72"))
		return *reinterpret_cast<StateVectorComponent**>((uintptr_t)this + 0x118 + (8 * 32));
	else if (Utils::File::getVersion() == _("1.21.71"))
		return *reinterpret_cast<StateVectorComponent**>((uintptr_t)this + 0x118 + (8 * 32));
	else if (Utils::File::getVersion() == _("1.21.70"))
		return *reinterpret_cast<StateVectorComponent**>((uintptr_t)this + 0x118 + (8 * 32));
	else
		return *reinterpret_cast<StateVectorComponent**>((uintptr_t)this + 0x118 + (8 * 32));
}

auto Actor::getAABBShapeComponent() -> AABBShapeComponent* {
	if (Utils::File::getVersion() == _("1.21.80"))
		return *reinterpret_cast<AABBShapeComponent**>((uintptr_t)this + 0x118 + (8 * 34));
	else if (Utils::File::getVersion() == _("1.21.73"))
		return *reinterpret_cast<AABBShapeComponent**>((uintptr_t)this + 0x118 + (8 * 33));
	else if (Utils::File::getVersion() == _("1.21.72"))
		return *reinterpret_cast<AABBShapeComponent**>((uintptr_t)this + 0x118 + (8 * 33));
	else if (Utils::File::getVersion() == _("1.21.71"))
		return *reinterpret_cast<AABBShapeComponent**>((uintptr_t)this + 0x118 + (8 * 33));
	else if (Utils::File::getVersion() == _("1.21.70"))
		return *reinterpret_cast<AABBShapeComponent**>((uintptr_t)this + 0x118 + (8 * 33));
	else
		return *reinterpret_cast<AABBShapeComponent**>((uintptr_t)this + 0x118 + (8 * 33));
}

auto Actor::getActorRotationComponent() -> ActorRotationComponent* {
	if (Utils::File::getVersion() == _("1.21.80"))
		return *reinterpret_cast<ActorRotationComponent**>((uintptr_t)this + 0x118 + (8 * 35));
	else if (Utils::File::getVersion() == _("1.21.73"))
		return *reinterpret_cast<ActorRotationComponent**>((uintptr_t)this + 0x118 + (8 * 34));
	else if (Utils::File::getVersion() == _("1.21.72"))
		return *reinterpret_cast<ActorRotationComponent**>((uintptr_t)this + 0x118 + (8 * 34));
	else if (Utils::File::getVersion() == _("1.21.71"))
		return *reinterpret_cast<ActorRotationComponent**>((uintptr_t)this + 0x118 + (8 * 34));
	else if (Utils::File::getVersion() == _("1.21.70"))
		return *reinterpret_cast<ActorRotationComponent**>((uintptr_t)this + 0x118 + (8 * 34));
	else
		return *reinterpret_cast<ActorRotationComponent**>((uintptr_t)this + 0x118 + (8 * 34));
}

auto Actor::getActorWalkAnimationComponent() -> ActorWalkAnimationComponent* {
	//return *reinterpret_cast<ActorWalkAnimationComponent**>((uintptr_t)this + 0x118 + (8 * 35));
	//return *reinterpret_cast<ActorWalkAnimationComponent**>((uintptr_t)this + 0x118 + (8 * 34));
	return new ActorWalkAnimationComponent();
}

auto Actor::getActorEquipmentComponent() -> ActorEquipmentComponent* {
	static void* sig = nullptr;
	if (!sig) {
		sig = Utils::Memory::FindPattern(_("4C 8B 41 48 4C 8B D1 48 8B 41 50 4C 8B 49 68 49 2B C0 8B 12 48 C1 F8 03 48 FF C8 25 36"));
	}
	return reinterpret_cast<ActorEquipmentComponent * (__fastcall*)(uintptr_t a1, uint32_t * a2)>(sig)(getEntityContext().basicregistry, &getEntityContext().id);
}

auto Actor::getMoveInputComponent() -> MoveInputComponent* {
	static void* sig = nullptr;
	if (!sig) {
		sig = Utils::Memory::FindPattern(_("4C 8B 41 48 4C 8B D1 48 8B 41 50 4C 8B 49 68 49 2B C0 8B 12 48 C1 F8 03 48 FF C8 25 2E"));
	}
	return reinterpret_cast<MoveInputComponent * (__fastcall*)(uintptr_t a1, uint32_t * a2)>(sig)(getEntityContext().basicregistry, &getEntityContext().id);
}

auto Actor::getRuntimeIDComponent() -> RuntimeIDComponent* {
	static void* sig = nullptr;
	if (!sig) {
		sig = Utils::Memory::FindPattern(_("4C 8B 41 48 4C 8B D1 48 8B 41 50 4C 8B 49 68 49 2B C0 8B 12 48 C1 F8 03 48 FF C8 25 14 14"));
	}
	return reinterpret_cast<RuntimeIDComponent * (__fastcall*)(uintptr_t a1, uint32_t * a2)>(sig)(getEntityContext().basicregistry, &getEntityContext().id);
}

auto Actor::getActorTypeComponent() -> ActorTypeComponent* {
	static void* sig = nullptr;
	if (!sig) {
		sig = Utils::Memory::FindPattern(_("4C 8B 41 48 4C 8B D1 48 8B 41 50 4C 8B 49 68 49 2B C0 8B 12 48 C1 F8 03 48 FF C8 25 14 AD"));
	}
	return reinterpret_cast<ActorTypeComponent * (__fastcall*)(uintptr_t a1, uint32_t * a2)>(sig)(getEntityContext().basicregistry, &getEntityContext().id);
}

auto Actor::getAttributeComponent() -> AttributeComponent* {
	static void* sig = nullptr;
	if (!sig) {
		sig = Utils::Memory::FindPattern(_("4C 8B 51 08 41 BB 44"));
	}
	return reinterpret_cast<AttributeComponent * (__fastcall*)(EntityContext&)>(sig)(getEntityContext());
}

auto Actor::getRenderPositionComponent() -> RenderPositionComponent* {
	static void* sig = nullptr;
	if (!sig) {
		sig = Utils::Memory::FindPattern(_("4C 8B 41 48 41 BB 6E"));
	}
	return reinterpret_cast<RenderPositionComponent * (__fastcall*)(uintptr_t a1, uint32_t * a2)>(sig)(getEntityContext().basicregistry, &getEntityContext().id);
}

auto Actor::getHurtTime() -> int16_t {
	return *reinterpret_cast<int16_t*>((uintptr_t)this + 0x19C);
}

auto Actor::isInvisible() -> bool {
	static auto func = reinterpret_cast<bool(__thiscall*)(void*)>((*reinterpret_cast<void***>(this))[31]);
	
	return func(this);
}

auto Actor::isAlive() -> bool {
	static auto func = reinterpret_cast<bool(__thiscall*)(void*)>((*reinterpret_cast<void***>(this))[47]);

	return func(this);
}

auto Actor::isOnFire() -> bool {
	static auto func = reinterpret_cast<bool(__thiscall*)(void*)>((*reinterpret_cast<void***>(this))[48]);

	return func(this);
}

auto Actor::canSee(const Actor& target, ShapeType obstructionType) -> bool {
	static void* sig;
	if (!sig) {
		if (Utils::File::getVersion() == _("1.21.73")) {
			sig = Utils::Memory::FindPattern(_("E8 85 DF 3B"));
			sig = (void*)((uintptr_t)sig + 5 + *reinterpret_cast<int*>((uintptr_t)sig + 1));
		}
		else if (Utils::File::getVersion() == _("1.21.72")) {
			sig = Utils::Memory::FindPattern(_("E8 25 DC 3B FD"));
			sig = (void*)((uintptr_t)sig + 5 + *reinterpret_cast<int*>((uintptr_t)sig + 1));
		}
		else if (Utils::File::getVersion() == _("1.21.71")) {
			sig = Utils::Memory::FindPattern(_("E8 E5 F1 3B"));
			sig = (void*)((uintptr_t)sig + 5 + *reinterpret_cast<int*>((uintptr_t)sig + 1));
		}
		else if (Utils::File::getVersion() == _("1.21.70")) {
			sig = Utils::Memory::FindPattern(_("E8 E5 F1 3B"));
			sig = (void*)((uintptr_t)sig + 5 + *reinterpret_cast<int*>((uintptr_t)sig + 1));
		}
		else {
			sig = Utils::Memory::FindPattern(_("E8 45 C2 73"));
			sig = (void*)((uintptr_t)sig + 5 + *reinterpret_cast<int*>((uintptr_t)sig + 1));
		}
	}

	return reinterpret_cast<bool(__fastcall*)(Actor*, const Actor&, ShapeType)>(sig)(this, target, obstructionType);
}

auto Actor::getNameTag() -> std::string {
	static void* sig;
	if (!sig) {
		sig = Utils::Memory::FindPattern(_("48 83 EC 28 48 8B 81 28 01 00 00 48 85 C0 74 4F"));
	}
	static auto func = reinterpret_cast<std::string32 * (__fastcall*)(Actor*)>(sig);
	return func(this)->c_str();
	/*

	if (Utils::File::getVersion() == _("1.21.73"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC50)->c_str();
	else if (Utils::File::getVersion() == _("1.21.72"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC50)->c_str();
	else if (Utils::File::getVersion() == _("1.21.71"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC50)->c_str();
	else if (Utils::File::getVersion() == _("1.21.70"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC50)->c_str();
	else
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC58)->c_str();*/
}

auto Actor::getLocalNameTag() -> std::string {
	if (Utils::File::getVersion() == _("1.21.80"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC08)->c_str();
	else if (Utils::File::getVersion() == _("1.21.73"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC50)->c_str();
	else if (Utils::File::getVersion() == _("1.21.72"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC50)->c_str();
	else if (Utils::File::getVersion() == _("1.21.71"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC50)->c_str();
	else if (Utils::File::getVersion() == _("1.21.70"))
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC50)->c_str();
	else
		return reinterpret_cast<std::string32*>((uintptr_t)this + 0xC58)->c_str();
}

auto Actor::getEntityIdentifier() -> std::string {
	return reinterpret_cast<std::string32*>((uintptr_t)this + 0x240)->c_str();
}

auto Actor::getSkin() -> SerializedSkin* {
	return reinterpret_cast<SerializedSkin*>((uintptr_t)this + 4516);
}
