using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;

namespace WS
{
    [ObjectSystem]
    public class TimerComponentAwakeSystem : AwakeSystem<TimerComponent>
    {
        public override void Awake(TimerComponent self)
        {
            self.Awake();
        }
    }

    [ObjectSystem]
    public class TimerComponentUpdateSystem : UpdateSystem<TimerComponent>
    {
        public override void Update(TimerComponent self)
        {
            self.Update();
        }
    }

    ///<summary>时间管理器</summary>
    public class TimerComponent : SingleComponent<TimerComponent>
    {
        ///<summary>所有时间实体</summary>
        private List<TimerEntity> ListTimes = new List<TimerEntity>();
        ///<summary>协程载体</summary>
        private Init Mono;
        ///<summary>是否暂停</summary>
        public bool IsPause;

        public void Awake()
        {
            Mono = GameObject.FindObjectOfType<Init>();
        }

        public void Update()
        {
            if (!IsPause)
            {
                for (int i = ListTimes.Count - 1; i >= 0; i--)
                {
                    if (!ListTimes[i].IsPause)
                    {
                        ListTimes[i].UseTime += Time.deltaTime;
                        ListTimes[i].OnUpdate?.Invoke(ListTimes[i].UseTime);
                        if (ListTimes[i].UseTime >= ListTimes[i].WaitTime && !ListTimes[i].IsPause)
                        {
                            if (ListTimes[i].Tcs == null)
                            {
                                ListTimes[i].OnCallback?.Invoke();
                                if (ListTimes[i].IsLoop)
                                {
                                    ListTimes[i].UseTime = 0;
                                }
                                else
                                {
                                    ListTimes[i].Dispose();
                                    ListTimes.Remove(ListTimes[i]);
                                }
                            }
                            else
                            {
                                ListTimes[i].Tcs.SetResult(true);
                                ListTimes[i].Dispose();
                                ListTimes.Remove(ListTimes[i]);
                            }
                        }
                    }
                }
            }
        }

        ///<summary>异步时间等待器</summary>
        public Task WaitAsync(float time)
        {
            TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
            TimerEntity entity = ComponentFactory.CreateWithParent<TimerEntity>(this);
            entity.WaitTime = time;
            entity.Tcs = tcs;
            ListTimes.Add(entity);
            return tcs.Task;
        }

        /// <summary>创建时间等待器(是暂停状态需要手动开始)</summary>
        /// <param name="time">等待时间</param>
        /// <param name="oncallback">时间到后的回调</param>
        /// <param name="onupdate">帧逻辑</param>
        /// <param name="loop">循环</param>
        public TimerEntity Create(float time, Action oncallback = null, bool loop = false, Action<float> onupdate = null)
        {
            TimerEntity entity = ComponentFactory.CreateWithParent<TimerEntity>(this);
            entity.WaitTime = time;
            entity.OnCallback = oncallback;
            entity.OnUpdate = onupdate;
            entity.IsLoop = loop;
            entity.IsPause = true;
            ListTimes.Add(entity);
            return entity;
        }

        /// <summary>创建时间等待器(创建并执行)</summary>
        /// <param name="time">等待时间</param>
        /// <param name="oncallback">时间到后的回调</param>
        public TimerEntity Wait(float time, Action oncallback)
        {
            return Wait(time, oncallback, false, null);
        }

        /// <summary>创建时间等待器(创建并执行)</summary>
        /// <param name="time">等待时间</param>
        /// <param name="oncallback">时间到后的回调</param>
        /// <param name="loop">循环</param>
        public TimerEntity Wait(float time, Action oncallback, bool loop)
        {
            return Wait(time, oncallback, loop, null);
        }

        /// <summary>创建时间等待器(创建并执行)</summary>
        /// <param name="time">等待时间</param>
        /// <param name="oncallback">时间到后的回调</param>
        /// <param name="onupdate">帧逻辑</param>
        /// <param name="loop">循环</param>
        public TimerEntity Wait(float time, Action oncallback = null, bool loop = false, Action<float> onupdate = null)
        {
            TimerEntity entity = ComponentFactory.CreateWithParent<TimerEntity>(this);
            entity.WaitTime = time;
            entity.OnCallback = oncallback;
            entity.OnUpdate = onupdate;
            entity.IsLoop = loop;
            ListTimes.Add(entity);
            return entity;
        }

        ///<summary>停止并销毁</summary>
        public void Stop(TimerEntity entity)
        {
            if (ListTimes.Exists(t => t == entity))
            {
                entity.IsPause = true;
                entity.Dispose();
                ListTimes.Remove(entity);
            }
        }

        ///<summary>开启Mono协程(不受IsPause控制)</summary>
        public Coroutine StartCoroutine(IEnumerator routine)
        {
            return Mono.StartCoroutine(routine);
        }

        ///<summary>停止Mono协程</summary>
        public void StopCoroutine(IEnumerator routine)
        {
            Mono.StopCoroutine(routine);
        }

        public override void Dispose()
        {
            base.Dispose();
            IsPause = false;
            for (int i = 0; i < ListTimes.Count; i++)
            {
                ListTimes[i].Dispose();
            }
            ListTimes.Clear();
            Mono.StopAllCoroutines();
            Mono = null;
        }
    }
}