using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class ItimerEvent {
    public double remainingLen = 0;
    public int remainingType = 0;//0 每帧率 1 间隔帧数 2 间隔s数
    public double intervalLen = 0;//间隔时间
    //public int firstDelayType = 0;//首次特殊延迟时长  -1 当前不是首次运行
    //public int repetitionSize = 0;//总共重复次数
    public int remainingRepetition = 0;//剩余重复次数
    public timeEventBack m_back = null;

    public int update(double timeLen)//-1 终止 0 触发一次回调 1 不做后续响应
    {
        if (remainingRepetition < 0) return -1;
        if (remainingType == 0) return 0;

        if (remainingType == 1)
        {
            remainingLen = remainingLen - 1;
            if (remainingLen <= 0)
            {
                remainingLen = intervalLen;
                return 0;
            }
        }
        remainingLen -= timeLen;
        if (remainingLen <= 0.000000001)
        {
            remainingLen = intervalLen;
            return 0;
        }
        return 1;
    }
    public bool back(String name)//true 保留 false 终止
    {
        if (remainingRepetition < 0) return false;
        if(this.remainingType != 0)
        {
            this.remainingRepetition = this.remainingRepetition - 1;
        }
        return m_back(name);

    }
}
public class Itimer : MonoBehaviour
{
    protected Dictionary<string, ItimerEvent> times = new Dictionary<string, ItimerEvent>();
    protected List<string> removeTimeList = new List<string>();
    protected List<string> nowBacks = new List<string>();
    void Start()
    {
    }
    private void clear_update()
    {
        nowBacks.Clear();
        if (removeTimeList.Count > 0)
        {
            for (int i = 0; i < removeTimeList.Count; i++)
            {
                if (times.ContainsKey(removeTimeList[i]))
                {
                    times.Remove(removeTimeList[i]);
                }
            }
            removeTimeList.Clear();
        }
    }
    // Update is called once per frame
    void Update()
    {
        clear_update();
        if (times.Count == 0) {
            return;
        }
        foreach (var item in times)
        {
            ItimerEvent itimerEvent = item.Value;
            int state = itimerEvent.update(Time.deltaTime);
            if(state == -1)
            {
                removeTimeList.Add(item.Key);
            }else if(state == 0)
            {
                nowBacks.Add(item.Key);
            }
        }
        foreach(var key in nowBacks)
        {
            ItimerEvent itimerEvent = times[key];
            if(removeTimeList.IndexOf(key) < 0)//防止这里面的回调逻辑取消后边队列的定时事件，在同一帧率的情况下出现多余回调
            {
                if(itimerEvent.back(key) == false)
                {
                    removeTimeList.Add(key);
                }
            }
        }
    }
    public void clear()
    {
        clear_update();
        times.Clear();
    }
    //不支持重复的name，如果要替换请至少间隔一个帧调用
    public bool addTimer_Sec(string name, timeEventBack back,double intervalLen,uint loopRepetitionLen)
    {
        if(intervalLen < 0.1)
        {
            return false;
        }
        if (this.times.ContainsKey(name) || back == null)
        {
            return false;
        }
        var itimerEvent = new ItimerEvent();
        itimerEvent.remainingType = 2;
        itimerEvent.remainingRepetition = (int)loopRepetitionLen;
        itimerEvent.remainingLen = intervalLen;
        itimerEvent.intervalLen = intervalLen;
        itimerEvent.m_back = back;
        times.Add(name,itimerEvent);
        return true;
    }
    public void delTimer(string name)
    {
        if (times.ContainsKey(name)) times.Remove(name);
    }
    public bool addTimer_Update(string name, timeEventBack back, int intervalLen, int loopRepetitionLen)
    {
        if (intervalLen < 0)
        {
            return false;
        }
        if (this.times.ContainsKey(name) || back == null)
        {
            return false;
        }
        var itimerEvent = new ItimerEvent();
        itimerEvent.remainingType = loopRepetitionLen == -1 ? 0 : 1;
        itimerEvent.remainingRepetition = loopRepetitionLen >= 0 ? loopRepetitionLen : 1;
        itimerEvent.remainingLen = intervalLen;
        itimerEvent.intervalLen = intervalLen;
        itimerEvent.m_back = back;
        times.Add(name, itimerEvent);
        return true;
    }
    public void OnDestroy()
    {
        if(times != null) times.Clear();
        if (nowBacks != null) nowBacks.Clear();
    }
}
