﻿
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

public class HitboxManager : UdonSharpBehaviour
{
    [Header("Some values are not yet functionally implemented and/or improperly implemented and will be changed!")]
    [HideInInspector]
    public ClassChange ActiveClassChange;

    [HideInInspector]
    public SubClassChange ActiveSubClassChange;

    //Copied from the prevous version
    public Transform CurrentSpawnpoint;

    public Transform HUDPivot;
    //public TMPro.TextMeshProUGUI MaxHealthText;
    //public TMPro.TextMeshProUGUI HealthText;
    public Animator HUDAnimator;
    [Header(""), Tooltip("Only set when Initialize Combat System is enabled")]
    public float MaxHealth = 2000;
    [Tooltip("Turn off if you have another UDON script enable it!")]
    public bool InitializeCombatSystem = true;

    [Header("")]
    public float ChestDMG = 200;
    public float ChestDMGShieldRatio = 0.5f;

    [Header("")]
    public float HeadDMG = 1900;
    public float HeadDMGShieldRatio = 0.75f;

    bool ShieldActivated = false;

    [Header("")]
    public float DOTDMG = 280;
    public float DOTEffectRatio = 0.8f;
    int DOTTicks = 0;

    [Header("")]
    public float HOTAmount = 250;
    int HOTTicks = 0;

    [Header("To be tested")]
    public float ElectricDMG = 80;

    [Header("")]
    public float FireDMG = 280;
    int FireTicks = 0;

    [Header("")]
    public float PoisonDMG = 280;
    bool Poisoned = false;

    [Header("Not implemented")]
    public float RadDMG = 280;
    //bool RadWait = false;

    [Header("")]
    public float IceDMG = 80;
    public float IceEffectRatio = 0.4f;
    int IceTicks = 0;

    [Header("")]
    public float StunEffectRatio = 0.1f;
    bool StunActivated = false;

    [Header("")]
    public float SlowEffectRatio = 0.6f;
    bool SlowActivated = false;

    [Header("")]
    public float SpeedEffectRatio = 1.8f;
    bool SpeedActivated = false;

    int CancelTicks = 0;

    [Header("Not implemented")]
    public float RepairAmount = 0;


    [Header("")]
    public float JumpSpeed = 5;
    public float RunSpeed = 5;
    public float WalkSpeed = 3;
    public float StrafeSpeed = 3;
    Transform HeadProxy;

    // Probally needed, not sure sure about the IsValid though...
    bool PlayerCheck(VRCPlayerApi playerApi)
    {

        if (playerApi != null)
        {
            if (playerApi.IsValid())
            {
                return true;
            }
        }
        return false;
    }
    private void Start()
    {
        if(InitializeCombatSystem)
        {
            if (PlayerCheck(Networking.LocalPlayer))
            {
                Networking.LocalPlayer.CombatSetMaxHitpoints(MaxHealth);
                Networking.LocalPlayer.CombatSetCurrentHitpoints(MaxHealth);
                Networking.LocalPlayer.CombatSetup();
                Networking.LocalPlayer.SetJumpImpulse(JumpSpeed);
                Networking.LocalPlayer.SetRunSpeed(RunSpeed);
                Networking.LocalPlayer.SetWalkSpeed(WalkSpeed);
                Networking.LocalPlayer.SetStrafeSpeed(StrafeSpeed);

                Networking.LocalPlayer.CombatSetRespawn(true, 5, CurrentSpawnpoint);
                ChangeClass();
            }
        }
    }
    public override void OnPlayerJoined(VRCPlayerApi playerApi)
    {
        if (InitializeCombatSystem)
        {
            if (PlayerCheck(playerApi))
            {
                playerApi.CombatSetMaxHitpoints(MaxHealth);
                playerApi.CombatSetCurrentHitpoints(MaxHealth);
                playerApi.CombatSetup();
            }
        }
    }
    public void ChangeClass()
    {
        if(ActiveClassChange != null)
        {
            ActiveClassChange.ChangeClass();
            ActiveSubClassChange.ChangeClass();
            Networking.LocalPlayer.SetJumpImpulse(JumpSpeed);
            Networking.LocalPlayer.SetRunSpeed(RunSpeed);
            Networking.LocalPlayer.SetWalkSpeed(WalkSpeed);
            Networking.LocalPlayer.SetStrafeSpeed(StrafeSpeed);
        }
    }
    public void TakeHeal(float healing)
    {
        if (PlayerCheck(Networking.LocalPlayer))
        {
            if (Networking.LocalPlayer.CombatGetCurrentHitpoints() > 0)
            {
                Networking.LocalPlayer.CombatSetCurrentHitpoints(Mathf.Clamp(Networking.LocalPlayer.CombatGetCurrentHitpoints() + healing, 0, MaxHealth));
            }
        }

    }
    
    public void OnHOT()
    {
        if (CancelTicks > 0)
        {
        }
        else
        {
            if (HOTTicks <= 0)
            {
                if (HUDAnimator)
                {
                    HUDAnimator.SetBool("HOT", true);
                }
                HOTTicks = 5;
                SendCustomEventDelayedSeconds("HOTTick", 1);
            }
        }
    }
    public void HOTTick()
    {
        if (CancelTicks > 0)
        {
            if (HUDAnimator)
            {
                HUDAnimator.SetBool("HOT", false);
            }
        }
        else
        {
            HOTTicks--;
            TakeHeal(HOTAmount);
            PoisonEnd();
            if (HOTTicks > 0)
            {
                SendCustomEventDelayedSeconds("HOTTick", 1);
            }
            else
            {
                if (HUDAnimator)
                {
                    HUDAnimator.SetBool("HOT", false);
                }
            }
        }
    }

    public void OnDOT()
    {
        if (DOTTicks <= 0)
        {
            if (HUDAnimator)
            {
                HUDAnimator.SetBool("DOT", true);
            }
            DOTTicks = 5;
            SendCustomEventDelayedSeconds("DOTTick", 1);
        }
    }

    public void DOTTick()
    {
        DOTTicks--;
        TakeDamage(DOTDMG);
        if (DOTTicks > 0)
        {
            SendCustomEventDelayedSeconds("DOTTick", 1);
        }
        else
        {
            if (HUDAnimator)
            {
                HUDAnimator.SetBool("DOT", false);
            }
        }
    }

    public void OnFire()
    {
        if (FireTicks <= 0)
        {
            FireTicks = 5;
            if (HUDAnimator)
            {
                HUDAnimator.SetBool("Fire", true);
            }
            TakeDamage(FireDMG);
            SendCustomEventDelayedSeconds("FireTick", 1);
        }
    }
    public void FireTick()
    {
        FireTicks--;
        TakeDamage(FireDMG);
        if (FireTicks > 0)
        {
            SendCustomEventDelayedSeconds("FireTick", 1);
        }
        else
        {
            if (HUDAnimator)
            {
                HUDAnimator.SetBool("Fire", false);
            }
        }
    }

    public void OnElectric()
    {
        TakeDamage(ElectricDMG);
        ShieldEnd();
        if (HUDAnimator)
        {
            HUDAnimator.SetBool("Electric", true);
        }
        SendCustomEventDelayedSeconds("ElectricEnd", 1);
    }

    public void ElectricEnd()
    {

        if (HUDAnimator)
        {
            HUDAnimator.SetBool("Electric", false);
        }
    }

    public void OnStun()
    {
        if (!StunActivated)
        {
            if (HUDAnimator)
            {
                HUDAnimator.SetBool("Stun", true);
            }
            StunActivated = true;
            SendCustomEventDelayedSeconds("StunEnd", 4);
        }
    }

    public void StunEnd()
    {
        if (HUDAnimator)
        {
            HUDAnimator.SetBool("Stun", false);
        }
        StunActivated = false;
    }

    public void OnSlow()
    {
        if(!SlowActivated)
        {
            if (HUDAnimator)
            {
                HUDAnimator.SetBool("Slow", true);
            }
            SlowActivated = true;
            SendCustomEventDelayedSeconds("SlowEnd", 8);
        }
    }

    public void SlowEnd()
    {
        if (HUDAnimator)
        {
            HUDAnimator.SetBool("Slow", false);
        }
        SlowActivated = false;
    }

    public void OnSpeed()
    {
        if (CancelTicks > 0)
        {
        }
        else
        {
            if (!SpeedActivated)
            {
                SpeedActivated = true;
                if (HUDAnimator)
                {
                    HUDAnimator.SetBool("Speed", true);
                }
                SendCustomEventDelayedSeconds("SpeedEnd", 8);
            }
        }
    }

    public void SpeedEnd()
    {
        if (HUDAnimator)
        {
            HUDAnimator.SetBool("Speed", false);
        }
        SpeedActivated = false;
    }

    public void OnShield()
    {
        if (CancelTicks > 0)
        {
        }
        else
        {
            if (!ShieldActivated)
            {
                if (HUDAnimator)
                {
                    HUDAnimator.SetBool("Shield", true);
                }
                ShieldActivated = true;
                SendCustomEventDelayedSeconds("ShieldEnd", 20);
            }
        }
    }

    public void ShieldEnd()
    {
        if (HUDAnimator)
        {
            HUDAnimator.SetBool("Shield", false);
        }
        ShieldActivated = false;
    }

    public void OnPoison()
    {
        if(!Poisoned)
        {
            if (HUDAnimator)
            {
                HUDAnimator.SetBool("Poison", true);
            }
            Poisoned = true;
            TakeDamage(PoisonDMG);
            SendCustomEventDelayedSeconds("PoisonTick", 3);
        }
    }

    public void PoisonTick()
    {
        if(Poisoned)
        {
            if (HUDAnimator)
            {
                HUDAnimator.SetBool("Poison", true);
            }
            TakeDamage(PoisonDMG);
            SendCustomEventDelayedSeconds("PoisonTick", 3);
        }
        else
        {
            PoisonEnd();
        }
    }
    
    public void PoisonEnd()
    {
        if (HUDAnimator)
        {
            HUDAnimator.SetBool("Poison", false);
        }
    }

    public void OnCancel()
    {
        if (CancelTicks <= 0)
        {
            ShieldEnd();
            SpeedEnd();
            HOTTicks = 0;
            if (HUDAnimator)
            {
                HUDAnimator.SetBool("Cancel", true);
            }
            SendCustomEventDelayedSeconds("CancelTick", 1);
        }
    }

    public void CancelTick()
    {
        if (CancelTicks > 0)
        {
            SendCustomEventDelayedSeconds("CancelTick", 1);
        }
        else
        {
            CancelEnd();
        }
    }

    public void CancelEnd()
    {
        if (HUDAnimator)
        {
            HUDAnimator.SetBool("Cancel", false);
        }
    }

    public void OnIce()
    {
        if (IceTicks <= 0)
        {
            if (HUDAnimator)
            {
                HUDAnimator.SetBool("Ice", true);
            }
            TakeDamage(IceDMG);
            SendCustomEventDelayedSeconds("IceTick", 8);
        }
    }

    public void IceTick()
    {
        if (IceTicks > 0)
        {
            TakeDamage(IceDMG);
            SendCustomEventDelayedSeconds("IceTick", 8);
        }
        else
        {
            IceEnd();
        }
    }

    public void IceEnd()
    {

        if (HUDAnimator)
        {
            HUDAnimator.SetBool("Ice", false);
        }
    }

    public void OnDamageHead()
    {
        if(ShieldActivated)
        {
            TakeDamage(HeadDMG * HeadDMGShieldRatio);
        }
        else
        {
            TakeDamage(HeadDMG);
        }
    }

    public void OnDamageChest()
    {
        if (ShieldActivated)
        {
            TakeDamage(ChestDMG * ChestDMGShieldRatio);
        }
        else
        {
            TakeDamage(ChestDMG);
        }
    }

    public void TakeDamage(float damage)
    {
        if(PlayerCheck(Networking.LocalPlayer))
        {
            if (Networking.LocalPlayer.CombatGetCurrentHitpoints() > 0)//Prevent extra damage when ragdolled
            {
                Networking.LocalPlayer.CombatSetCurrentHitpoints(Networking.LocalPlayer.CombatGetCurrentHitpoints() - damage);

                if (Networking.LocalPlayer.CombatGetCurrentHitpoints() <= 0)
                {

                    OnDeath();
                }

            }
        }
        
    }

    public void OnDeath()
    {
        FireTicks = 0;
        HOTTicks = 0;
        //Not needed?
        //Networking.LocalPlayer.CombatSetCurrentHitpoints(MaxHealth);

    }

    //Moved to here to be smoother visually
    private void LateUpdate()
    {
        if (HeadProxy)
        {
            if(HUDPivot)
            {
                HUDPivot.SetPositionAndRotation(HeadProxy.position, HeadProxy.rotation);
                //Experimental: IPD scaling for HUD
                HUDPivot.localScale = HeadProxy.lossyScale;
            }
        }
    }
    private void Update()
    {
        VRCPlayerApi vrcpapi = Networking.LocalPlayer;

        if (PlayerCheck(vrcpapi))
        {
            if (HeadProxy)
            {
                float CurrentRunSpeed = RunSpeed;
                float CurrentStrafeSpeed = StrafeSpeed;
                float CurrentWalkSpeed = WalkSpeed;
                if (DOTTicks > 0)
                {
                    CurrentRunSpeed *= DOTEffectRatio;
                    CurrentStrafeSpeed *= DOTEffectRatio;
                    CurrentWalkSpeed *= DOTEffectRatio;
                }

                if (IceTicks > 0)
                {
                    CurrentRunSpeed *= IceEffectRatio;
                    CurrentStrafeSpeed *= IceEffectRatio;
                    CurrentWalkSpeed *= IceEffectRatio;
                }

                if (StunActivated)
                {
                    CurrentRunSpeed *= StunEffectRatio;
                    CurrentStrafeSpeed *= StunEffectRatio;
                    CurrentWalkSpeed *= StunEffectRatio;
                }

                if (SlowActivated)
                {
                    CurrentRunSpeed *= SlowEffectRatio;
                    CurrentStrafeSpeed *= SlowEffectRatio;
                    CurrentWalkSpeed *= SlowEffectRatio;
                }

                if (SpeedActivated)
                {
                    CurrentRunSpeed *= SpeedEffectRatio;
                    CurrentStrafeSpeed *= SpeedEffectRatio;
                    CurrentWalkSpeed *= SpeedEffectRatio;
                }

                vrcpapi.SetRunSpeed(CurrentRunSpeed);
                vrcpapi.SetStrafeSpeed(CurrentStrafeSpeed);
                vrcpapi.SetWalkSpeed(CurrentWalkSpeed);
            
                transform.SetPositionAndRotation(HeadProxy.position, vrcpapi.GetRotation());
                if(HUDAnimator)
                {
                    HUDAnimator.SetFloat("Health", Mathf.Clamp01(Mathf.Clamp(vrcpapi.CombatGetCurrentHitpoints(),0, MaxHealth) /MaxHealth)-Mathf.Epsilon, 0.1f, Time.deltaTime);
                }
            }
            else
            {
                GameObject headProxyObject = GameObject.Find("Head Proxy");
                if (headProxyObject)
                {
                    HeadProxy = headProxyObject.transform;
                    //vrcpapi.CombatSetDamageGraphic(headProxyObject);
                    headProxyObject.SetActive(false);
                }
            }
        }

    }
}
