﻿using System;
using System.Linq.Expressions;
using JLGames.RocketDriver.CSharp.DateTimex;
using UnityEngine;
using UnityEngine.Events;

namespace JLGames.RocketDriver.Actions.DateTimex
{
    public class MonoTimeSeries : MonoBehaviour
    {
        [Serializable]
        public class TimeSeriesUnit
        {
            [SerializeField] [Tooltip("Slice Name\n时间片名称")]
            private string m_SliceName;

            [SerializeField] [Tooltip("Slice Start Space(ms)\n时间片开始间隔(毫秒)")]
            private long m_StartSpace;

            [SerializeField] [Tooltip("Slice Duration(ms)\n时间片持续时间(毫秒)")]
            private long m_Duration;

            /// <summary>
            /// Slice Name
            /// 时间片名称
            /// </summary>
            public string SliceName => m_SliceName;

            /// <summary>
            /// Slice Start Space(ms)
            /// 时间片开始间隔(毫秒)
            /// </summary>
            public long StartSpace => m_StartSpace;

            /// <summary>
            /// Slice Duration(ms)
            /// 时间片持续时间(毫秒)
            /// </summary>
            public long Duration => m_Duration;
        }

        /// <summary>
        /// UnityEvent callback for when a slice is started or finished.
        /// 切片开始或结束时的 UnityEvent 回调。
        /// </summary>
        [Serializable]
        public class SliceEvent : UnityEvent<string>
        {
        }

        /// <summary>
        /// UnityEvent callback when slice is switched.
        /// 切片切换时的 UnityEvent 回调。
        /// </summary>
        [Serializable]
        public class SliceChangeEvent : UnityEvent<string, string>
        {
        }

        [Tooltip("Enable Loop\n启用时间片循环")] [SerializeField]
        private bool m_Loop;

        [Tooltip("Time slice definition\n时间片定义")] [SerializeField]
        private TimeSeriesUnit[] m_Slices;

        /// <summary>
        /// Slice Start Event
        /// 时间片开始
        /// </summary>
        [Tooltip("Slice Start Event\n时间片开始")] public SliceEvent OnSliceStart;

        /// <summary>
        /// Slice End Event
        /// 时间片结束
        /// </summary>
        [Tooltip("Slice End Event\n时间片结束")] public SliceEvent OnSliceEnd;

        /// <summary>
        /// Slice Change Event
        /// 时间片切换
        /// </summary>
        [Tooltip("Slice Change Event\n时间片切换")] public SliceChangeEvent OnSliceChange;

        private string m_SliceName;
        private TimeSeries m_Series;

        private void Start()
        {
            m_Series = new TimeSeries(DateTimeUtil.NowTicks1970, m_Loop);
            foreach (var unit in m_Slices)
            {
                m_Series.AddSlice(unit.SliceName, unit.StartSpace * DateTimeUtil.TicksPerMilliSecond,
                    unit.Duration * DateTimeUtil.TicksPerMilliSecond);
            }
        }

        private void FixedUpdate()
        {
            var now = DateTimeUtil.NowTicks1970;
            var newSliceName = m_Series.LocateTo(now);
            if (newSliceName == m_SliceName) return;
            if (string.IsNullOrEmpty(newSliceName) && string.IsNullOrEmpty(m_SliceName)) return;

            // 旧为空
            if (string.IsNullOrEmpty(m_SliceName))
            {
                OnSliceStart.Invoke(newSliceName);
                goto CatchBlock;
            }

            // 新为空
            if (string.IsNullOrEmpty(newSliceName))
            {
                OnSliceEnd.Invoke(m_SliceName);
                goto CatchBlock;
            }

            // 没有空
            OnSliceEnd.Invoke(m_SliceName);
            OnSliceStart.Invoke(newSliceName);
            OnSliceChange.Invoke(newSliceName, m_SliceName);

            CatchBlock:
            m_SliceName = newSliceName;
        }
    }
}