using System;
using UnityEngine;

public delegate void SimpleTimerTick();

public class SimpleTimer
{
    bool hasTime = false;
    float t;
    private int tSeconds;
    public float TimeLeft {  get { return t; } }
    public bool Active = false;
    public SimpleTimerTick OnFinish = null;

    public Action<int> OnSecondsChanged = null;
        

    float timeScale = 1;
    public float TimeScale { get { return timeScale; } set { timeScale = value; } }

    public bool IgnoreFirstUpdate = true;

    private float duration;
    protected bool loop = false;

    private EnterFrameManager efm;
    public SimpleTimer()
    {
        efm = GameObject.FindObjectOfType<EnterFrameManager>();
    }

    public SimpleTimer(float time, SimpleTimerTick callback, bool loop = false)
    {
        efm = GameObject.FindObjectOfType<EnterFrameManager>();
        Start(time, callback, loop);
    }

    public void Start(float time, SimpleTimerTick callback, bool loop = false)
    {
        hasTime = true;
        this.loop = loop;
        OnFinish = callback;
        this.duration = time;
        this.t = time;
        SetTSeconds();            
        efm.Add(this, delegate (float t) { Update(t); });
        Active = true;
        IgnoreFirstUpdate = true;
    }

    private void SetTSeconds()
    {
        int oldTSeconds = tSeconds;
        this.tSeconds = Math.Max(0, (int)Math.Ceiling(t));
        if (oldTSeconds != tSeconds && this.OnSecondsChanged != null)
        {
            OnSecondsChanged(tSeconds);
        }
    }

    public void Stop()
    {
        if (!Active) return;
        efm.Remove(this);
        Active = false;
        OnFinish = null;
    }

    private int pauseCount = 0;
    public bool Paused { get { return pauseCount > 0; } }

    public void Pause()
    {
        if (!Active) return;
        pauseCount++;
        if (pauseCount == 1)
        {
            efm.Remove(this);
        }
    }

    public void Resume()
    {
        if (pauseCount == 0 || !hasTime) return;
        pauseCount--;
        if (pauseCount == 0)
        {
            efm.Add(this, delegate (float t) { Update(t); });
        }
    }

    public void SetTime(float t)
    {
        this.t = t;
        SetTSeconds();
    }

    public void AddTime(float a)
    {
        this.t += a;
        SetTSeconds();
    }

    public void Update(float timeElapsed)
    {
        if (IgnoreFirstUpdate)
        {
            IgnoreFirstUpdate = false;
            return;
        }

        if (!Active) return;
        if (Paused) return;

        t -= (timeElapsed * timeScale);
        SetTSeconds();

        if (t <= 0)
        {
            float actualTime = duration - t;
            if (loop)
            {
                t += duration;
                SetTSeconds();
            }
            else
            {
                t = 0;
                SetTSeconds();

                Active = false;
                efm.Remove(this);
            }

            if (OnFinish != null) OnFinish();
        }
    }

}