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

public class StatusEffectInstance : MonoBehaviour
{
    public bool canStack;
    public bool canRefresh;

    [Header("Set by code:")]
    public PhotonView owner;


    public bool IsActive => effectStateCoroutine != null;

    public float endEffectTime;

    public List<StatusEffect> activeStacks = new List<StatusEffect>();

    public UnityEvent OnEffectStackAddedEvent = new UnityEvent();
    public UnityEvent OnEffectEnded = new UnityEvent();

    protected Coroutine effectStateCoroutine;

    protected virtual void Awake()
    {
        owner = GetComponentInParent<PhotonView>();
    }

    public virtual void ApplyEffect(StatusEffect effect)
    {
        if (CanAddStack())
        {
            AddStack(effect);
        }
        else if(CanRefresh())
        {
            RefreshEffect(effect);
        }
    }

    protected virtual void AddStack(StatusEffect addedEffect)
    {
        activeStacks.Add(addedEffect);
        OnEffectStackAdded();
    }

    protected virtual bool CanAddStack()
    {
        return canStack || (!canStack && activeStacks.Count <= 0);
    }
    protected virtual bool CanRefresh()
    {
        return canRefresh;
    }

    protected virtual float GetHighestDuration()
    {
        float highestDuration = 0;
        for (int i = activeStacks.Count - 1; i >= 0; i--)
        {
            if (activeStacks[i].duration > highestDuration)
                highestDuration = activeStacks[i].duration;
        }
        return highestDuration;
    }

    protected virtual void RefreshEffect(StatusEffect effect)
    {

    }

    protected virtual void OnEffectStackAdded()
    {
        UpdateEndEffectTime();

        if (!IsActive)
            effectStateCoroutine = StartCoroutine(EffectStateCoroutine());

        OnEffectStackAddedEvent.Invoke();
    }

    protected virtual void UpdateEndEffectTime()
    {
        endEffectTime = Time.time + GetHighestDuration();
    }

    protected virtual IEnumerator EffectStateCoroutine()
    {
        EffectStateStarted();

        while (Time.time < endEffectTime)
        {
            yield return null;
        }

        EffectStateEnded();
    }

    protected virtual void EffectStateStarted()
    {

    }

    protected virtual void EffectStateEnded()
    {
        effectStateCoroutine = null;

        activeStacks.Clear();
        OnEffectEnded.Invoke();
    }

}
