using System;

namespace XGame.Framework.Time
{
    public class Alarm : IAlarm, IDisposable
    {
        public enum AlarmRunState : sbyte
        {
            None,
            Running,
            Stoped,
            Finished,
        }

        private long _triggerTimeStamp;
        private long _curTimeStamp;
        private Action _action;
        private AlarmRunState _runState;
        public AlarmRunState State
        {
            get => _runState;
            private set
            {
                _runState = value;
                if (value is AlarmRunState.Stoped or AlarmRunState.Finished)
                {
                    try
                    {
                        Listener?.OnCompleted(this);
                    }
                    catch (Exception ex)
                    {
                        Log.Exception($"闹钟事件监听执行异常.", ex);
                    }
                    Listener = null;
                }
            }
        }
        public ITimeListener<IAlarm> Listener { get; set; }
        public Alarm(Action action, long curTimeStamp, long triggerTimeStamp)
        {
#if UNITY_EDITOR
            UnityEngine.Assertions.Assert.IsTrue(triggerTimeStamp > curTimeStamp, "设置闹钟触发时间不能小于或者等于当前时间");
#endif
            _triggerTimeStamp = triggerTimeStamp;
            _curTimeStamp = curTimeStamp;
            _action = action;
            State = AlarmRunState.Running;
        }

        public void SetTime(long timestamp)
        {
            if (State == AlarmRunState.Running)
            {
                _curTimeStamp = timestamp;
            }
        }

        public void Cancel()
        {
            State = AlarmRunState.Stoped;
            _action = null;
        }

        public bool Update(int elapse)
        {
            if (State != AlarmRunState.Running)
            {
                return true;
            }

            _curTimeStamp += elapse;
            if (_curTimeStamp >= _triggerTimeStamp)
            {
                State = AlarmRunState.Finished;
                try
                {
                    _action?.Invoke();
                }
                catch (Exception e)
                {
                    Log.Exception("闹钟回调执行发生异常", e);
                    //throw new Exception($"闹钟回调执行发生异常:{e}");
                }
                return true;
            }

            return false;
        }

        public void Dispose()
        {
            _action = null;
            Listener = null;
        }
    }
}