#include "HitEffects.h"

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

auto HitEffects::onViewPerspectiveAfter(int* perspective) -> void {
	perspective_ = *perspective;
}

auto HitEffects::onClient() -> void {
	/*
	for (Setting* setting : Client::findSettingWithID(this, 0)) {
		setting->name = Datas::Language::get().module.render.hiteffects.mode;

		//setting->list[0] = Datas::Language::get().module.render.hiteffects.mode_1;
	}
	for (Setting* setting : Client::findSettingWithID(this, 1)) {
		setting->name = Datas::Language::get().module.render.hiteffects.delay;
	}
	for (Setting* setting : Client::findSettingWithID(this, 2)) {
		setting->name = Datas::Language::get().module.render.hiteffects.removedelay;
	}
	for (Setting* setting : Client::findSettingWithID(this, 3)) {
		setting->name = Datas::Language::get().module.render.hiteffects.roundness;
	}
	for (Setting* setting : Client::findSettingWithID(this, 4)) {
		setting->name = Datas::Language::get().module.render.hiteffects.size;
		setting->visible = mode == 0;
	}
	for (Setting* setting : Client::findSettingWithID(this, 5)) {
		setting->name = Datas::Language::get().module.render.hiteffects.amount;
	}
	for (Setting* setting : Client::findSettingWithID(this, 6)) {
		setting->name = Datas::Language::get().module.render.hiteffects.speed;
	}*/

	name = Datas::Language::get().module.render.hiteffects.name;
	description = Datas::Language::get().module.render.hiteffects.description;

	if (!enabled) return;

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

	auto localplayer = clientinstance->getLocalPlayer();
	if (!localplayer) {
		renderdatas.clear();
		return;
	}
}

auto HitEffects::onAttack(Actor& actor) -> void {
	auto clientinstance = Client::clientinstance;
	if (!clientinstance) return;

	auto blocksource = clientinstance->getBlockSource();
	if (!blocksource) return;

	long long now = Utils::Time::getMs();
	static long long start = Utils::Time::getMs();
	if (now - start >= removedelay * (delay * 1000.f)) {
		glm::vec3 position = Utils::Move::getPosition((Player*)&actor);

		for (int i = 0; i < static_cast<int>(amount); i++) {
			float x = Utils::Math::getrandom(-0.75f, 0.75f);
			float y = Utils::Math::getrandom(-0.75f, 0.75f);
			float z = Utils::Math::getrandom(-0.75f, 0.75f);
			glm::vec3 compposition = glm::vec3(
				position.x + x,
				position.y + y,
				position.z + z
			);
			int falls = -1;
			glm::ivec3 icompposition_ = glm::ivec3(
				static_cast<int>(compposition.x),
				static_cast<int>(compposition.y - 0.1f),
				static_cast<int>(compposition.z)
			);
			for (int i = 0; i < 100; i++) {
				if (blocksource->getBlock(&icompposition_)->getBlockLegacy()->getName() != _("tile.air")) {
					falls = i;
					break;
				}
				icompposition_.y -= i;
			}
			if (falls == -1)
				falls = 100;


			ImColor color = ImColor();
			switch (mode) {
			case 0:
				color = Utils::Color::getColor(3.f, 0, 0.f);
				break;
			case 1:
				std::vector<std::pair<float, ImColor>> list = {
						{ 0.f, ImColor(0.4f, 0.f, 0.f, 0.f)},
						{ 0.5f, ImColor(0.5f, 0.f, 0.f, 0.f)},
						{ 1.f, ImColor(0.6f, 0.f, 0.f, 0.f)},
				};
				color = Utils::Color::getWaveColor(3.f, 0, list);
				break;
			}

			renderdatas.push_back({ now, compposition, compposition, color, falls });
		}
		start = now;
	}
}

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

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

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

	long long now = Utils::Time::getMs();

	Utils::ImGuiRender::setDrawList(ImGui::GetBackgroundDrawList());

	switch (mode) {
	case 0:
		Utils::ImGuiRender::setSegments(roundness);

		for (int i = 0; i < renderdatas.size(); i++) {
			renderdatas[i].color.Value.w = Utils::Math::animate((now - renderdatas[i].start >= removedelay * 2500.f) ? 0.f : 1.f, renderdatas[i].color.Value.w, Client::deltaTime);
			if (renderdatas[i].color.Value.w < 0.01f) continue;

			ImVec2 pos = Utils::ImGuiRender::getWorldPosition(renderdatas[i].pos);
			if (pos.x > 0.f && pos.y > 0.f) {

				float distance = Utils::Math::getDistance(Utils::Move::getEyePosition(localplayer), renderdatas[i].pos);
				Utils::ImGuiRender::setSize(((size * 2.f) / (distance / perspective_ != 0 ? 2.f : 1.f)) * renderdatas[i].color.Value.w);

				Utils::ImGuiRender::setColor(renderdatas[i].color);
				Utils::ImGuiRender::fillCircle(pos);

				Utils::ImGuiRender::setSize(((size * 2.f) / (distance / perspective_ != 0 ? 2.f : 1.f)) * (renderdatas[i].color.Value.w + 0.25f));
				Utils::ImGuiRender::setThickness(((size * 2.f) / (distance / perspective_ != 0 ? 2.f : 1.f)) * (renderdatas[i].color.Value.w + 0.25f));
				Utils::ImGuiRender::fillShadowCircle(pos);
			}

			if (renderdatas[i].pos.y - renderdatas[i].dipos.y > -(renderdatas[i].falls - 1)) {
				renderdatas[i].pos.y -= renderdatas[i].dupe * speed;
				renderdatas[i].dupe += 0.0025f;
			}
		}
		break;
	case 1:
		Utils::ImGuiRender::setRound(0.f);

		for (int i = 0; i < renderdatas.size(); i++) {
			renderdatas[i].color.Value.w = Utils::Math::animate((now - renderdatas[i].start >= removedelay * 2500.f) ? 0.f : 1.f, renderdatas[i].color.Value.w, Client::deltaTime);
			if (renderdatas[i].color.Value.w < 0.01f) continue;

			ImVec2 pos = Utils::ImGuiRender::getWorldPosition(renderdatas[i].pos);
			if (pos.x > 0.f && pos.y > 0.f) {

				float distance = Utils::Math::getDistance(Utils::Move::getEyePosition(localplayer), renderdatas[i].pos);
				Utils::ImGuiRender::setColor(renderdatas[i].color);
				ImVec4 rectpos = ImVec4(pos.x - size, pos.y - size, pos.x + size, pos.y + size);
				Utils::ImGuiRender::fillRectangle(rectpos);
			}

			if (renderdatas[i].pos.y - renderdatas[i].dipos.y > -(renderdatas[i].falls - 1)) {
				renderdatas[i].pos.y -= renderdatas[i].dupe * speed;
				renderdatas[i].dupe += 0.0025f;
			}
		}
		break;
	}
}

auto HitEffects::onDimensionChanged() -> void {
	renderdatas.clear();
}
