using System;
using System.Collections.Generic;
using Comfort.Common;
using EFT;
using EFT.Interactive;
using EFT.InputSystem;
using EscapeFromTarkovCheat.Data;
using EscapeFromTarkovCheat.Feauters;
using EscapeFromTarkovCheat.Feauters.ESP;
using EscapeFromTarkovCheat.Utils;
using UnityEngine;
using System.Security.Cryptography;
using EscapeFromTarkovCheat.Features.Misc;
using System.Diagnostics;
using EscapeFromTarkovCheat.Features;
using System.Linq;
using System.ComponentModel.Design;
namespace EscapeFromTarkovCheat
{
    public class Main : MonoBehaviour
    {
        public static List<GamePlayer> GamePlayers = new List<GamePlayer>();
        public static Player LocalPlayer;
        public static GameWorld GameWorld;
        public static Camera MainCamera;

        public static Skills skills = new Skills();

        private float _nextPlayerCacheTime;
        private static readonly float _cachePlayersInterval = 4f;

        // Stamina BEGIN
        private float _aimDrainRate;
        private float _aimRangeFinderDrainRate;
        private float _sprintDrainRate;
        private float _jumpConsumption;
        private float _proneConsumption;

        private Vector3 _aimConsumptionByPose;
        private Vector3 _overweightConsumptionByPose;
        private Vector2 _crouchConsumption;
        private Vector2 _standupConsumption;
        private Vector2 _walkConsumption;

        private float _oxygenRestoration;
        private float _exhaustedMeleeSpeed;

        private float _baseRestorationRate;

        private bool _staminaExhaustionCausesJiggle;
        private bool _staminaExhaustionRocksCamera;
        private bool _staminaExhaustionStartsBreathSound;

        private bool _isConfigured = false;
        // Stamina END

        public void Awake()
        {
            GameObject hookObject = new GameObject();
            // MAIN
            hookObject.AddComponent<Menu.UI.Menu>();
            // ESP
            hookObject.AddComponent<PlayerESP>();
            hookObject.AddComponent<ItemESP>();
            hookObject.AddComponent<LootableContainerESP>();
            hookObject.AddComponent<ExfiltrationPointsESP>();
            // AIMBOT
            hookObject.AddComponent<Aimbot>();
            // MISC
            hookObject.AddComponent<SpeedHack>();
            DontDestroyOnLoad(hookObject);
            LocalisationManager.Initialize();
        }

        public static bool notReady() {
            return Singleton<GameWorld>.Instance == null || // Not in raid
                Singleton<GameWorld>.Instance.RegisteredPlayers == null || // Not yet loaded
                Camera.main == null; // Counting down
        }

        public static void KillEverything()
        {
            var gameWorld = Singleton<GameWorld>.Instance;
            if (gameWorld == null) return;

            foreach (var player in gameWorld.AllAlivePlayersList.Where(players => !players.IsYourPlayer))
            {
                player.ActiveHealthController.Kill(EDamageType.Bullet);
            }
        }

        public static void TeleportLoot()
        {
            var targetPosition = GameUtils.GetTargetPosition();
            var lootItems = FindObjectsOfType<LootItem>()
                .Where(GameUtils.IsGroundLoot)
                .Where(GameUtils.IsInteractableLoot)
                .Select(lootItem => new GameLootItem(lootItem))
                .ToList();

            int itemCount = lootItems.Count;
            float radius = 2.0f;
            float additionalSpacing = 1f;

            for (int i = 0; i < itemCount; i++)
            {
                var angle = i * Mathf.PI * 2 / itemCount;
                var x = Mathf.Cos(angle) * (radius + (i * additionalSpacing / itemCount));
                var z = Mathf.Sin(angle) * (radius + (i * additionalSpacing / itemCount));

                lootItems[i].LootItem.transform.position = new Vector3(targetPosition.x + x, targetPosition.y, targetPosition.z + z);
            }
        }

        public static void TeleportAllEnemies()
        {
            if (notReady())
                return;

            var targetPosition = GameUtils.GetTargetPosition();
            foreach (var player in GameWorld.AllAlivePlayersList.Where(x => !x.IsYourPlayer))
            {
                player.Teleport(targetPosition);
            }
        }

        private void RefreshData()
        {
            if (Time.time < _nextPlayerCacheTime)
                return;
            if (notReady())
                return;
            GameWorld = Singleton<GameWorld>.Instance;
            MainCamera = Camera.main;
            _nextPlayerCacheTime = (Time.time + _cachePlayersInterval);
        }
        private void RefreshPlayers()
        {
            if (notReady())
                return;

            GamePlayers.Clear();
            foreach (Player player in GameWorld.RegisteredPlayers)
            {
                if (player.IsYourPlayer)
                {
                    LocalPlayer = player;
                    continue;
                }

                if (!GameUtils.IsPlayerAlive(player) || (Vector3.Distance(MainCamera.transform.position, player.Transform.position) > Settings.DrawPlayersDistance))
                    continue;

                GamePlayers.Add(new GamePlayer(player));
            }
            
            foreach (GamePlayer gamePlayer in GamePlayers)
                gamePlayer.RecalculateDynamics();
        }

        public static void UnlockAllDoors() {
            if (notReady())
                return;

            foreach (var door in FindObjectsOfType<Door>())
            {
                if (door.DoorState == EDoorState.Open)
                    continue;
                if (Vector3.Distance(door.transform.position, LocalPlayer.Position) > 20f)
                    continue;

                door.DoorState = EDoorState.Shut;
            }
        }

        public static void Heal() {
            if (notReady())
                return;

            if (LocalPlayer.PlayerHealthController == null)
                return;

            if (LocalPlayer.PlayerHealthController.IsBodyPartBroken(EBodyPart.Head))
                LocalPlayer.PlayerHealthController.RestoreBodyPart(EBodyPart.Head, 1);
            if (LocalPlayer.PlayerHealthController.IsBodyPartBroken(EBodyPart.LeftArm))
                LocalPlayer.PlayerHealthController.RestoreBodyPart(EBodyPart.LeftArm, 1);
            if (LocalPlayer.PlayerHealthController.IsBodyPartBroken(EBodyPart.RightArm))
                LocalPlayer.PlayerHealthController.RestoreBodyPart(EBodyPart.RightArm, 1);
            if (LocalPlayer.PlayerHealthController.IsBodyPartBroken(EBodyPart.LeftLeg))
                LocalPlayer.PlayerHealthController.RestoreBodyPart(EBodyPart.LeftLeg, 1);
            if (LocalPlayer.PlayerHealthController.IsBodyPartBroken(EBodyPart.RightLeg))
                LocalPlayer.PlayerHealthController.RestoreBodyPart(EBodyPart.RightLeg, 1);
            if (LocalPlayer.PlayerHealthController.IsBodyPartBroken(EBodyPart.Chest))
                LocalPlayer.PlayerHealthController.RestoreBodyPart(EBodyPart.Chest, 1);
            if (LocalPlayer.PlayerHealthController.IsBodyPartBroken(EBodyPart.Stomach))
                LocalPlayer.PlayerHealthController.RestoreBodyPart(EBodyPart.Stomach, 1);
            LocalPlayer.PlayerHealthController.RestoreFullHealth();
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.Head, LocalPlayer.PlayerHealthController.GetBodyPartHealth(EBodyPart.Head).Maximum, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.Stomach, LocalPlayer.PlayerHealthController.GetBodyPartHealth(EBodyPart.Stomach).Maximum, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.Chest, LocalPlayer.PlayerHealthController.GetBodyPartHealth(EBodyPart.Chest).Maximum, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.LeftLeg, LocalPlayer.PlayerHealthController.GetBodyPartHealth(EBodyPart.LeftLeg).Maximum, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.RightLeg, LocalPlayer.PlayerHealthController.GetBodyPartHealth(EBodyPart.RightLeg).Maximum, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.LeftArm, LocalPlayer.PlayerHealthController.GetBodyPartHealth(EBodyPart.LeftArm).Maximum, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.RightArm, LocalPlayer.PlayerHealthController.GetBodyPartHealth(EBodyPart.RightArm).Maximum, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.Head, 9999, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.Stomach, 9999, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.Chest, 9999, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.LeftLeg, 9999, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.RightLeg, 9999, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.LeftArm, 9999, default);
            LocalPlayer.PlayerHealthController.ChangeHealth(EBodyPart.RightArm, 9999, default);
        }
        private void GodMode() {
            if (notReady())
                return;

            if (LocalPlayer.ActiveHealthController == null)
                return;

            if (LocalPlayer.ActiveHealthController.DamageCoeff != -1f)
            {
                LocalPlayer.ActiveHealthController.SetDamageCoeff(-1f);
                LocalPlayer.ActiveHealthController.RemoveNegativeEffects(EBodyPart.Common);
                LocalPlayer.ActiveHealthController.RestoreFullHealth();
                LocalPlayer.ActiveHealthController.ChangeEnergy(999f);
                LocalPlayer.ActiveHealthController.ChangeHydration(999f);
                LocalPlayer.ActiveHealthController.DoPermanentHealthBoost(25f);
                LocalPlayer.ActiveHealthController.RemoveMedEffect();
            }
            if (LocalPlayer.ActiveHealthController.FallSafeHeight != 9999999f)
            {
                LocalPlayer.ActiveHealthController.FallSafeHeight = 9999999f;
            }
        }

        private void GodMode_OnDisable()
        {
            if (notReady())
                return;

            if (LocalPlayer.ActiveHealthController == null)
                return;
            LocalPlayer.ActiveHealthController.SetDamageCoeff(1f);
            LocalPlayer.ActiveHealthController.FallSafeHeight = 1f;
            LocalPlayer.ActiveHealthController.ChangeEnergy(100f);
            LocalPlayer.ActiveHealthController.ChangeHydration(100f);
            LocalPlayer.ActiveHealthController.RemoveMedEffect();
            LocalPlayer.ActiveHealthController.DoPermanentHealthBoost(0f);
        }

        private void Stamina_Configure() {
            if (notReady())
                return;

            if (LocalPlayer.Physical == null)
                return;

            if (LocalPlayer.Physical.StaminaParameters == null)
                return;
            var parameters = LocalPlayer.Physical.StaminaParameters;
            _aimDrainRate = parameters.AimDrainRate;
            _aimRangeFinderDrainRate = parameters.AimRangeFinderDrainRate;
            _sprintDrainRate = parameters.SprintDrainRate;
            _jumpConsumption = parameters.JumpConsumption;
            _proneConsumption = parameters.ProneConsumption;

            _aimConsumptionByPose = parameters.AimConsumptionByPose;
            _overweightConsumptionByPose = parameters.OverweightConsumptionByPose;

            _crouchConsumption = parameters.CrouchConsumption;
            _standupConsumption = parameters.StandupConsumption;
            _walkConsumption = parameters.WalkConsumption;

            _oxygenRestoration = parameters.OxygenRestoration;
            _exhaustedMeleeSpeed = parameters.ExhaustedMeleeSpeed;

            _baseRestorationRate = parameters.BaseRestorationRate;

            _staminaExhaustionCausesJiggle = parameters.StaminaExhaustionCausesJiggle;
            _staminaExhaustionRocksCamera = parameters.StaminaExhaustionRocksCamera;
            _staminaExhaustionStartsBreathSound = parameters.StaminaExhaustionStartsBreathSound;

            _isConfigured = true;
        }

        private void Stamina() {
            if (notReady())
                return;

            if (LocalPlayer.Physical == null)
                return;

            if (LocalPlayer.Physical.StaminaParameters == null)
                return;

            var parameters = LocalPlayer.Physical.StaminaParameters;
            if (!_isConfigured)
                Stamina_Configure();

            LocalPlayer.PlayerHealthController.SetStaminaCoeff(3000000);
            parameters.AimDrainRate = 0f;
            parameters.AimRangeFinderDrainRate = 0f;
            parameters.SprintDrainRate = 0f;
            parameters.JumpConsumption = 0f;
            parameters.ProneConsumption = 0f;

            parameters.AimConsumptionByPose = Vector3.zero;
            parameters.OverweightConsumptionByPose = Vector3.zero;

            parameters.CrouchConsumption = Vector2.zero;
            parameters.StandupConsumption = Vector2.zero;
            parameters.WalkConsumption = Vector2.zero;

            parameters.OxygenRestoration = 10000f;
            parameters.ExhaustedMeleeSpeed = 10000f;
            parameters.BaseRestorationRate = parameters.Capacity;

            parameters.StaminaExhaustionCausesJiggle = false;
            parameters.StaminaExhaustionRocksCamera = false;
            parameters.StaminaExhaustionStartsBreathSound = false;
        }
        private void Stamina_OnDisable() {
            if (notReady())
                return;

            if (LocalPlayer.Physical == null)
                return;

            if (LocalPlayer.Physical.StaminaParameters == null)
                return;
            var parameters = LocalPlayer.Physical.StaminaParameters;
            parameters.AimDrainRate = _aimDrainRate;
            parameters.AimRangeFinderDrainRate = _aimRangeFinderDrainRate;
            parameters.SprintDrainRate = _sprintDrainRate;
            parameters.JumpConsumption = _jumpConsumption;
            parameters.ProneConsumption = _proneConsumption;

            parameters.AimConsumptionByPose = _aimConsumptionByPose;
            parameters.OverweightConsumptionByPose = _overweightConsumptionByPose;

            parameters.CrouchConsumption = _crouchConsumption;
            parameters.StandupConsumption = _standupConsumption;
            parameters.WalkConsumption = _walkConsumption;

            parameters.OxygenRestoration = _oxygenRestoration;
            parameters.ExhaustedMeleeSpeed = _exhaustedMeleeSpeed;

            parameters.BaseRestorationRate = _baseRestorationRate;

            parameters.StaminaExhaustionCausesJiggle = _staminaExhaustionCausesJiggle;
            parameters.StaminaExhaustionRocksCamera = _staminaExhaustionRocksCamera;
            parameters.StaminaExhaustionStartsBreathSound = _staminaExhaustionStartsBreathSound;
        }
        public static void IncreaseTraderStanding()
        {
            if (notReady())
                return;

            foreach (KeyValuePair<string, Profile.TraderInfo> info in LocalPlayer.Profile.TradersInfo)
            {
                string traderId = info.Key;
                Profile.TraderInfo traderInfo = info.Value;
                traderInfo.Init(traderId, LocalPlayer.Profile.Info);
                traderInfo.SetStanding(traderInfo.Standing + 0.10000000149011612);
            }
        }
        public static void CallAirdrop(bool takeNearbyPoint = false, Vector3 position = default(Vector3))
        {
            if (notReady())
                return;

            GameWorld.InitAirdrop(takeNearbyPoint, position);
        }

        public void Update()
        {
            RefreshData();
            if (Settings.DrawPlayers)
                RefreshPlayers();

            if (Input.GetKeyDown(Settings.UnlockDoors))
                UnlockAllDoors();

            if (Input.GetKeyDown(Settings.InstaHeal))
                Heal();

            if (Settings.GodMode)
            {
                Heal();
                GodMode();
            }
            else 
                GodMode_OnDisable();

            if (Settings.Stamina)
                Stamina();
            else 
                Stamina_OnDisable();

            if (Input.GetKeyDown(Settings.KillSwitch))
                KillEverything();

            if (Input.GetKeyDown(Settings.TpLoots))
                TeleportLoot();

            if (Input.GetKeyDown(Settings.IncreaseTraderStandingKey))
                IncreaseTraderStanding();

            if (Input.GetKeyDown(Settings.CallAirdrop))
                CallAirdrop(false, default(Vector3));

            if (Input.GetKeyDown(Settings.TpEnemies))
                TeleportAllEnemies();
        }
    }
}
