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

auto Trail::onClient() -> void {
	for (Setting* setting : Client::findSetting(this, _("Segs"))) {
		setting->visible = mode == 0;
	}

	if (!enabled) return;

	if (Client::screenName == _("start_screen")) return;

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

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

	if (renderdatas.size() > 1 && Utils::Math::getDistance(Utils::Move::getBlockPosition(localplayer), renderdatas[renderdatas.size() - 1].pos) < 0.1f)
		return;

	long long now = Utils::Time::getMs();
	static long long start = Utils::Time::getMs();
	if (now - start >= 1000.f / sps) {

		renderdatas.push_back({ now, Utils::Move::getBlockPosition(localplayer), Utils::Color::getColor(3.f, 0, 0.f)});

		start = now;
	}
}

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

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

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

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

		for (int i = 0; i < renderdatas.size(); i++) {
			renderdatas[i].color.Value.w = Utils::Math::animate((rps != 0.f && now - renderdatas[i].start >= 2000.f / rps) ? 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) {

				Utils::ImGuiRender::setSize(size * renderdatas[i].color.Value.w);

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

				Utils::ImGuiRender::setSize(size * (renderdatas[i].color.Value.w + 0.25f));
				Utils::ImGuiRender::setThickness(size * (renderdatas[i].color.Value.w + 0.25f));
				Utils::ImGuiRender::fillShadowCircle(pos);
			}
		}
		break;
	}
	case 1: {
		for (int i = 0; i < renderdatas.size(); i++) {
			renderdatas[i].color.Value.w = Utils::Math::animate((rps != 0.f && now - renderdatas[i].start >= 2000.f / rps) ? 0.f : 1.f, renderdatas[i].color.Value.w, Client::deltaTime);
			if (renderdatas[i].color.Value.w < 0.01f) continue;

			ImVec2 pos1, pos2;
			if (i < 1) {
				pos1 = Utils::ImGuiRender::getWorldPosition(renderdatas[i].pos);
				pos2 = Utils::ImGuiRender::getWorldPosition(renderdatas[i].pos);
			}
			else {
				pos1 = Utils::ImGuiRender::getWorldPosition(renderdatas[i - 1].pos);
				pos2 = Utils::ImGuiRender::getWorldPosition(renderdatas[i].pos);
			}

			if ((pos1.x > 0.f && pos1.y > 0.f) && (pos2.x > 0.f && pos2.y > 0.f)) {
				Utils::ImGuiRender::setThickness(size);
				Utils::ImGuiRender::setColor(renderdatas[i].color);
				Utils::ImGuiRender::drawLine(pos1, pos2);
			}
		}
		break;
	}
	}
}

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

auto Trail::getMode() -> std::string {
	switch (mode) {
	case 0:
		return _("Ball");
	case 1:
		return _("Line");
	}

	return _("Unknown");
}
