using System.Drawing;
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Cvars;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils;
using PubgMod.Main.Game;
using PubgMod.Players;

namespace PubgMod;

public class LandingManager
{
    private const float LandTime = 20f;
    private const string ParachuteMode = "models/props_survival/parachute/chute.vmdl";

    private readonly TimerSystem _timerSystem;
    private readonly PlayersManager _playersManager;
    private readonly ChatService _chatService;
    private readonly GameState _state;
    private readonly ConVar _fallDamageCvar;

    public LandingManager(PubgPlugin plugin, TimerSystem timerSystem, PlayersManager playersManager,
        ChatService chatService, GameState state)
    {
        _timerSystem = timerSystem;
        _playersManager = playersManager;
        _chatService = chatService;
        _state = state;
        _fallDamageCvar = ConVar.Find("sv_falldamage_scale")!;

        plugin.RegisterEventHandler<EventRoundStart>(OnRoundStart);
        plugin.RegisterEventHandler<EventPlayerSpawn>(OnPlayerSpawn);
        plugin.RegisterListener<Listeners.OnTick>(OnTick);
        plugin.RegisterListener<Listeners.OnServerPrecacheResources>(manifest => manifest.AddResource(ParachuteMode));
    }

    private HookResult OnPlayerSpawn(EventPlayerSpawn @event, GameEventInfo info)
    {
        if (_state.State != State.Playing)
            return HookResult.Continue;

        var player = @event.Userid;
        if (player == null || !player.IsValid || !player.PawnIsAlive)
            return HookResult.Continue;

        Server.NextWorldUpdate(() => OnSpawnFrame(player));
        return HookResult.Continue;
    }

    private void OnSpawnFrame(CCSPlayerController player)
    {
        //player.RemoveWeapons();
    }

    private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
    {
        if (_state.State != State.Playing)
            return HookResult.Continue;

        _timerSystem.AddRoundTimer(LandTime, LandPlayers);
        foreach (var player in _playersManager.LoadedPlayers)
        {
            var controller = player!.Controller;
            if (!controller.PawnIsAlive)
                continue;

            var pawn = controller.PlayerPawn.Value!;

            pawn.TakesDamage = false;
            pawn.VelocityModifier = 3f;
            pawn.RenderMode = RenderMode_t.kRenderNone;

            Utilities.SetStateChanged(pawn, "CCSPlayerPawn", "m_flVelocityModifier");
            Utilities.SetStateChanged(pawn, "CBaseModelEntity", "m_nRenderMode");

            pawn.Render = Color.FromArgb(0, 0, 0, 0);
            Utilities.SetStateChanged(pawn, "CBaseModelEntity", "m_clrRender");
            controller.RemoveWeapons();
            controller.PawnArmor = 0;
            controller.PawnHasHelmet = false;
        }

        _chatService.PrintToChatAll($"Game starts in {LandTime:0} seconds, select a landing position");


        return HookResult.Continue;
    }

    private void LandPlayers()
    {
        // Break all platforms
        foreach (var cBreakable in Utilities.FindAllEntitiesByDesignerName<CBreakable>("func_breakable")
                     .Where(e => e is { IsValid: true, Entity.Name: "platform" }))
        {
            cBreakable.AcceptInput("Break");
        }

        foreach (var player in _playersManager.LoadedPlayers)
        {
            if (!player!.Controller.PawnIsAlive)
                continue;

            var pawn = player.Controller.PlayerPawn.Value!;
            pawn.VelocityModifier = 1f;
            pawn.GravityScale = 0.2f;
            Utilities.SetStateChanged(pawn, "CCSPlayerPawn", "m_flVelocityModifier");

            pawn.TakesDamage = true;
            player.IsLanded = false;
            pawn.Teleport(velocity: Vector.Zero);
            CreateParachute(player);

            pawn.Render = Color.FromArgb(255, 255, 255, 255);
            Utilities.SetStateChanged(pawn, "CBaseModelEntity", "m_clrRender");
            player.Controller.GiveNamedItem("weapon_knife_t");
        }

        //_fallDamageCvar.SetValue(0f);
        //_chatService.PrintToChatAll("Game started, you're invinsible for 10 seconds");
        _chatService.PrintToChatAll("Game started");
        _timerSystem.AddRoundTimer(10f, DisableInvincibility);
    }

    private void OnTick()
    {
        foreach (var player in _playersManager.LoadedPlayers)
        {
            if (!player!.IsLanded && player.Controller.PawnIsAlive)
            {
                var pawn = player.Controller.PlayerPawn.Value;
                if (pawn == null)
                    continue;

                if (pawn.GroundEntity.Value != null)
                {
                    pawn.GravityScale = 1f;
                    player.IsLanded = true;

                    var parachute = player.ParachuteEntity?.Get();
                    if (parachute != null && parachute.IsValid)
                    {
                        parachute.AcceptInput("Kill");
                        player.ParachuteEntity = null;
                    }
                }
                else
                {
                    var velocity = pawn.AbsVelocity;
                    var newVelocity = new Vector(velocity.X, velocity.Y, -250f);
                    pawn.Teleport(velocity: newVelocity);
                }
            }
        }
    }

    private void DisableInvincibility()
    {
        foreach (var player in _playersManager.LoadedPlayers)
        {
            if (!player!.Controller.PawnIsAlive)
                continue;

            var pawn = player.Controller.PlayerPawn.Value!;
            //pawn.TakesDamage = true;
            pawn.RenderMode = RenderMode_t.kRenderNormal;
            Utilities.SetStateChanged(pawn, "CBaseModelEntity", "m_nRenderMode");
            pawn.CRenderComponent.EnableRendering = true;
        }

        // _fallDamageCvar.SetValue(1f);
        _chatService.PrintToChatAll("Invincibility disabled");
    }

    private void CreateParachute(PubgPlayer player)
    {
        var entity = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic_override")!;
        entity.MoveType = MoveType_t.MOVETYPE_NOCLIP;
        entity.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_NONE;
        entity.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_NONE;
        entity.DispatchSpawn();

        entity.Teleport(player.Controller.PlayerPawn.Value!.AbsOrigin);
        player.ParachuteEntity = new CHandle<CDynamicProp>(entity.EntityHandle.Raw);
        Server.NextFrame(() =>
        {
            entity.FireInput("SetParent", "!activator", player.Controller.PlayerPawn.Value);
            entity.SetModel(ParachuteMode);
        });
    }
}


why knife sometimes falls out of player(rarely)