using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using EFT;
using EFT.InventoryLogic;
using stupid.solutions.Data;
using stupid.solutions.stupid.solutions.Data;
using stupid.solutions.Utils;
using UnityEngine;

namespace stupid.solutions.Features.ESP;

public class PlayerESP : MonoBehaviour
{
	private static readonly Color _healthColor = Color.green;

	public static Color orange = Color.red;

	private Color violet = new Color(148f, 0f, 211f);

	public float lineLength = 20f;

	public float lineThickness = 2f;

	private static IEnumerator<Item> _equipItemList;

	private Color ItemColor = Color.white;

	private string _logFilePath;

	private static HashSet<int> processedEntities = new HashSet<int>();

	private static WildSpawnType WildSpawnType;

	private bool shouldclear = true;

	private bool shouldresetandclearchams;

	private static readonly float ItemListCacheInterval = 30f;

	private float _nextItemListCache;

	private Dictionary<Renderer, Shader> originalShaders = new Dictionary<Renderer, Shader>();

	private Dictionary<Renderer, (Color visibleColor, Color behindColor)> previousChamsColors = new Dictionary<Renderer, (Color, Color)>();

	private void Awake()
	{
		_logFilePath = Path.Combine(Application.persistentDataPath, "log.txt");
	}

	private void Log(string message)
	{
		using StreamWriter streamWriter = new StreamWriter(_logFilePath, append: true);
		streamWriter.WriteLine($"{DateTime.Now}: {message}");
	}

	public void Update()
	{
		if (Main.GameWorld == null && shouldclear)
		{
			processedEntities.Clear();
			shouldclear = false;
			originalShaders.Clear();
			previousChamsColors.Clear();
		}
		else if (Main.GameWorld != null && !shouldclear)
		{
			shouldclear = true;
		}
		if (Main.GameWorld == null)
		{
			return;
		}
		if (Camera.main != null)
		{
			Camera.main.useOcclusionCulling = false;
		}
		if (!Settings.PlayerInventoryESP)
		{
			return;
		}
		foreach (GamePlayer gamePlayer in Main.GamePlayers)
		{
			if (!(Time.time >= _nextItemListCache) || gamePlayer.Player.Profile.Inventory.Equipment.GetAllItems().Count() < 2)
			{
				continue;
			}
			int num = 0;
			foreach (ContainerItem lootItem in gamePlayer.LootItems)
			{
				num += lootItem.Count * lootItem.Item.StackObjectsCount;
			}
			if (gamePlayer.Player.Profile.Inventory.Equipment.GetAllItems().Count() != num)
			{
				gamePlayer.RefreshItems();
			}
			gamePlayer.RefreshItems();
			_nextItemListCache = Time.time + ItemListCacheInterval;
		}
	}

	public void OnGUI()
	{
		if (!Settings.DrawPlayers)
		{
			return;
		}
		if (Settings.Chams)
		{
			Chams();
		}
		foreach (GamePlayer gamePlayer in Main.GamePlayers)
		{
			if (!gamePlayer.IsOnScreen || gamePlayer.Player == Main.LocalPlayer || (gamePlayer.Distance > Settings.DrawPlayersDistance && !gamePlayer.isselected))
			{
				continue;
			}
			WildSpawnType role = gamePlayer.Player.Profile.Info.Settings.Role;
			Vector3 zero = Vector3.zero;
			zero = ((role == WildSpawnType.infectedAssault || role == WildSpawnType.infectedCivil || role == WildSpawnType.infectedLaborant || role == WildSpawnType.infectedPmc) ? GameUtils.GetBonePosByID(gamePlayer.Player, Aimbot.zombiebone) : GameUtils.GetBonePosByID(gamePlayer.Player, Settings.Aimbone));
			bool flag = Aimbot.CaulculateInFov(zero) <= Settings.AimbotFOV;
			int id = ((role == WildSpawnType.infectedAssault || role == WildSpawnType.infectedCivil || role == WildSpawnType.infectedLaborant || role == WildSpawnType.infectedPmc) ? 31 : 133);
			Vector3 bonePosByID = GameUtils.GetBonePosByID(gamePlayer.Player, id);
			RaycastHit raycastHit;
			bool flag2 = Aimbot.VisCheck(gamePlayer.Player.gameObject, Main.LocalPlayer.Fireport.position, bonePosByID, out raycastHit);
			float num = gamePlayer.HeadScreenPosition.y - 10f;
			float num2 = Math.Abs(gamePlayer.HeadScreenPosition.y - gamePlayer.ScreenPosition.y) + 10f;
			float num3 = num2 * 0.65f;
			if (Settings.DrawPlayerBox)
			{
				Vector2 position = new Vector2(gamePlayer.ScreenPosition.x - num3 / 2f, num);
				Vector2 size = new Vector2(num3, num2);
				Color color = ((!flag2) ? Settings.ESPBoxColor : Settings.boxsightline);
				Render.DrawCornerBox(position, size, 2f, color, 5f, centered: false);
			}
			if (Settings.DrawPlayerHealth)
			{
				if (Settings.DrawSimpleStrings)
				{
					if (flag)
					{
						DrawHealth(gamePlayer);
					}
				}
				else
				{
					DrawHealth(gamePlayer);
				}
			}
			if (Settings.DrawPlayerName)
			{
				(string playerText, string shorttext, Color playerColor) playerTextDetails = GameUtils.GetPlayerTextDetails(gamePlayer, role);
				string item = playerTextDetails.playerText;
				string item2 = playerTextDetails.shorttext;
				Color item3 = playerTextDetails.playerColor;
				Vector2 vector = GUI.skin.GetStyle(item).CalcSize(new GUIContent(item));
				string text = ((Settings.DrawSimpleStrings && flag) ? item : (Settings.DrawSimpleStrings ? item2 : item));
				if (!gamePlayer.isselected)
				{
					Render.DrawString(new Vector2(gamePlayer.HeadScreenPosition.x, num - vector.y - 3f), text, item3);
				}
				else
				{
					Render.DrawString(new Vector2(gamePlayer.HeadScreenPosition.x, num - vector.y - 3f), " [+] Selected Player : " + text + " [+] ", Settings.SelectedEntityColor);
				}
			}
			if (Settings.DrawPlayerLine)
			{
				Render.DrawLine(new Vector2(Screen.width / 2, Screen.height), new Vector2(gamePlayer.ScreenPosition.x, gamePlayer.ScreenPosition.y), 1.5f, flag2 ? Settings.isvisibleline : Settings.ESPLineColor);
			}
			if (Settings.playerWeapon && gamePlayer.Player.HandsController != null)
			{
				string text2 = string.Empty;
				if (gamePlayer.Player.HandsController.Item is Weapon)
				{
					Weapon weapon = (Weapon)gamePlayer.Player.HandsController.Item;
					_EF1A currentMagazine = weapon.GetCurrentMagazine();
					if (currentMagazine != null)
					{
						string arg = ColorUtility.ToHtmlStringRGB(Settings.EnemyAmmoCounterColor);
						text2 = $"<color=#{arg}>({currentMagazine.Count + weapon.ChamberAmmoCount}/{currentMagazine.MaxCount + weapon.ChamberAmmoCount}) </color>";
					}
				}
				if (Settings.playerWeapon)
				{
					if (text2 == string.Empty)
					{
						Render.DrawString(new Vector2(gamePlayer.ScreenPosition.x, gamePlayer.ScreenPosition.y + 6.5f), " " + gamePlayer.Player.HandsController.Item.ShortName.Localized() + " ", Settings.EnemyWeaponTextColor);
					}
					else
					{
						Render.DrawString(new Vector2(gamePlayer.ScreenPosition.x, gamePlayer.ScreenPosition.y + 6.5f), " " + gamePlayer.Player.HandsController.Item.ShortName.Localized() + " " + text2, Settings.EnemyWeaponTextColor, centered: true, default(Color), outline: false);
					}
				}
			}
			if (!Settings.PlayerInventoryESP)
			{
				continue;
			}
			int num4 = -20;
			HashSet<string> hashSet = new HashSet<string>();
			if (!gamePlayer.ItemInit)
			{
				gamePlayer.RefreshItems();
			}
			if (gamePlayer.LootItems == null)
			{
				break;
			}
			foreach (ContainerItem lootItem in gamePlayer.LootItems)
			{
				string localizedName = lootItem.LocalizedName;
				_ = lootItem.ItemID;
				if (GameUtils.ShouldDisplayItem(lootItem) && !hashSet.Contains(localizedName))
				{
					Color itemColor = GameUtils.GetItemColor(lootItem.Itemcat);
					string text3 = ((lootItem.Count > 1) ? $" ({lootItem.Count}) " : "");
					string text4 = (Settings.drawvalue ? $"[{lootItem.itemprice / 1000}K] " : "");
					Render.DrawString(new Vector2(gamePlayer.ScreenPosition.x, gamePlayer.ScreenPosition.y - (float)num4), "Has: " + lootItem.ShortName + text3 + text4 + ". ", itemColor);
					hashSet.Add(localizedName);
					num4 -= 20;
				}
			}
		}
	}

	private void Chams()
	{
		if (Main.GameWorld == null)
		{
			return;
		}
		foreach (GamePlayer gamePlayer in Main.GamePlayers)
		{
			if (gamePlayer.Distance > Settings.DrawPlayersDistance || gamePlayer.Player == Main.LocalPlayer || !Settings.Chams)
			{
				continue;
			}
			Renderer[] componentsInChildren = gamePlayer.Player.GetComponentsInChildren<Renderer>();
			bool flag = false;
			Renderer[] array = componentsInChildren;
			foreach (Renderer renderer in array)
			{
				if (renderer == null || renderer.material == null)
				{
					continue;
				}
				if (!originalShaders.ContainsKey(renderer))
				{
					originalShaders[renderer] = renderer.material.shader;
				}
				Color playerChamsVisible = Settings.PlayerChamsVisible;
				Color playerChamsHidden = Settings.PlayerChamsHidden;
				if (previousChamsColors.ContainsKey(renderer))
				{
					(Color, Color) tuple = previousChamsColors[renderer];
					if (tuple.Item1 == playerChamsVisible && tuple.Item2 == playerChamsHidden)
					{
						continue;
					}
					flag = true;
				}
				else
				{
					flag = true;
				}
				if (flag)
				{
					Shader shader = Main.bundle.LoadAsset<Shader>("wireframe.shader");
					if (!(shader == null))
					{
						renderer.material.shader = shader;
						renderer.material.SetColor("_VisibleColor", playerChamsVisible);
						renderer.material.SetColor("_InvisibleColor", playerChamsHidden);
						renderer.allowOcclusionWhenDynamic = false;
						renderer.forceRenderingOff = false;
						renderer.enabled = true;
						previousChamsColors[renderer] = (playerChamsVisible, playerChamsHidden);
					}
				}
			}
			processedEntities.Add(gamePlayer.Player.GetInstanceID());
		}
		if (Settings.Chams || !shouldresetandclearchams)
		{
			return;
		}
		foreach (GamePlayer gamePlayer2 in Main.GamePlayers)
		{
			ClearChams(gamePlayer2);
		}
	}

	private void ClearChams(GamePlayer gamePlayer)
	{
		Renderer[] componentsInChildren = gamePlayer.Player.GetComponentsInChildren<Renderer>();
		foreach (Renderer renderer in componentsInChildren)
		{
			if (!(renderer == null) && originalShaders.ContainsKey(renderer))
			{
				Shader shader = originalShaders[renderer];
				renderer.material.shader = shader;
				renderer.allowOcclusionWhenDynamic = true;
				renderer.forceRenderingOff = false;
				renderer.enabled = true;
			}
		}
		shouldresetandclearchams = true;
		processedEntities.Remove(gamePlayer.Player.GetInstanceID());
	}

	public void DrawHealth(GamePlayer gamePlayer)
	{
		float num = gamePlayer.HeadScreenPosition.y - 10f;
		float num2 = Math.Abs(gamePlayer.HeadScreenPosition.y - gamePlayer.ScreenPosition.y) + 10f;
		float num3 = num2 * 0.65f;
		if (gamePlayer.Player.HealthController.IsAlive)
		{
			float current = gamePlayer.Player.HealthController.GetBodyPartHealth(EBodyPart.Common).Current;
			float maximum = gamePlayer.Player.HealthController.GetBodyPartHealth(EBodyPart.Common).Maximum;
			Math.Floor(current);
			Math.Floor(maximum);
			float num4 = GameUtils.Map(current, 0f, maximum, 0f, num2);
			Color color = ((current / maximum < 0.5f) ? Color.red : _healthColor);
			float x = gamePlayer.ScreenPosition.x - num3 / 2f - 3f;
			float num5 = num + num2;
			Render.DrawLine(new Vector2(x, num5 - num4), new Vector2(x, num5), 3f, color);
		}
	}
}
