using UnityEngine;
using UnityEngine.Events;
using System.Collections;
using Photon.Pun;

public abstract class BaseDamageOverTimeEffectInstance : StatusEffectInstance
{
    public float currentDamagePerTick;
    public abstract DamageOverTimeType DamageType { get; }

    //public UnityEvent OnEffectApplied = new UnityEvent();
    public UnityEvent OnEffectTick = new UnityEvent();
    //public UnityEvent OnEffectEnded = new UnityEvent();

    protected float nextTickTime;

    protected override void Awake()
    {
        base.Awake();
        if (owner.IsMine)
        {
            OnEffectStackAddedEvent.AddListener(() => owner.RPC(nameof(RPC_EffectApplied) + DamageType.ToString(), RpcTarget.Others));
            OnEffectEnded.AddListener(() => owner.RPC(nameof(RPC_EffectEnded) + DamageType.ToString(), RpcTarget.Others));
        }
    }

    protected override void AddStack(StatusEffect addedEffect, float value)
    {
        DamageOverTimeEffect dotEffect = (DamageOverTimeEffect)addedEffect;
        currentDamagePerTick += value;
        base.AddStack(addedEffect, value);
    }

    protected override void RefreshEffect(StatusEffect effect, float value)
    {
        base.RefreshEffect(effect, value);
        currentDamagePerTick = GetHighestDamagePerTick(value);
        OnEffectStackAdded();
    }

    protected override IEnumerator EffectStateCoroutine()
    {
        nextTickTime = Time.time + ((DamageOverTimeEffect)activeStacks[0]).tickRate;

        while (Time.time < endEffectTime)
        {
            if (Time.time >= nextTickTime)
            {
                ApplyDamage();
                nextTickTime = Time.time + ((DamageOverTimeEffect)activeStacks[0]).tickRate;
            }
            yield return null;
        }

        EffectStateEnded();
    }

    protected virtual void ApplyDamage()
    {
        Health targetHealth = GetComponent<Health>();
        if (targetHealth != null)
        {
            targetHealth.ChangeValue(-currentDamagePerTick);
        }
        OnEffectTick.Invoke();
    }

    protected override void EffectStateStarted()
    {
        base.EffectStateStarted();
        OnEffectStackAddedEvent.Invoke();
    }

    protected override void EffectStateEnded()
    {
        currentDamagePerTick = 0;
        OnEffectEnded.Invoke();
        base.EffectStateEnded();
    }

    private float GetHighestDamagePerTick(float value)
    {
        float highestDamage = value;
        for (int i = activeStacks.Count - 1; i >= 0; i--)
        {
            if (((DamageOverTimeEffect)activeStacks[i]).baseDamagePerTick > highestDamage)
                highestDamage = ((DamageOverTimeEffect)activeStacks[i]).baseDamagePerTick;
        }
        return highestDamage;
    }

    [PunRPC]
    public void RPC_ApplyDamageOverTimeEffect(int effectIndex, float value)
    {
        ApplyEffect(StatusEffectIndexer.Instance.StatusEffects[effectIndex], value);
    }

    [PunRPC]
    public void RPC_EffectApplied()
    {
        OnEffectStackAddedEvent.Invoke();
    }

    [PunRPC]
    public void RPC_EffectEnded()
    {
        OnEffectEnded.Invoke();
    }
}

public enum DamageOverTimeType
{
    Burn,
    Poison,
    Bleed
    // Add more types as needed
}