using System.Linq;
using Entitas;
using UnityEngine;
using Game;
/// 
/// 实体减速、暂停 在此管理
/// 
public class PauseSystem : IExecuteSystem, IInitializeSystem
{
    private IGroup _entities;
    public void Initialize()
    {
        _entities = Util.GetGroup(GameMatcher.Pause);
    }
    public void Execute()
    {
        foreach (var entity in _entities)
        {
            UpdatePause(entity);
            UpdatePauseFix(entity); //确保至少播出1帧的
        }
    }
    private static void UpdatePause(GameEntity entity)
    {
        var pause = entity.pause;
        var isChange = false;
        if (pause.IsPause)
        {
            pause.PauseTime -= Time.deltaTime;
            pause.PauseTime = Mathf.Max(pause.PauseTime, 0);
            if (pause.PauseTime == 0)
            {
                pause.IsPause = false;
                isChange = true;
            }
        }
        else
        {
            if (pause.PausePreFrame > 0)
            {
                pause.PausePreFrame--;
            }
            else
            {
                if (pause.PauseTime > 0)
                {
                    pause.IsPause = true;
                    isChange = true;
                }
            }
        }
        if (entity.iD.Data.IsDestroy)
        {
            //即将销毁的 强制取消pause
            pause.IsPause = false;
            isChange = true;
        }
        if (!isChange)
            return;
        UpdateAnimPause(entity, pause.IsPause);
        UpdateEffectPause(entity, pause.IsPause);
        UpdateMovePause(entity, pause.IsPause);
        UpdateTimelinePause(entity, pause.IsPause);
    }
    private static void UpdateAnimPause(GameEntity entity, bool isPause)
    {
        if (!entity.hasAnimation)
            return;
        var anim = entity.animation;
        var pause = entity.pause;
        if (isPause)
        {
            pause.AnimeSpeedCache = anim.Animator.speed;
            anim.Animator.speed = 0;
        }
        else
        {
            anim.Animator.speed = pause.AnimeSpeedCache;
        }
    }
    private static void UpdateEffectPause(GameEntity entity, bool isPause)
    {
        if (!entity.hasView)
            return;
        var view = entity.view;
        foreach (var particle in view.EffectObject.Select(item => item.GameObject.GetComponent()))
        {
            switch (isPause)
            {
                case true when !particle.isPaused:
                    particle.Pause();
                    break;
                case false when particle.isPaused:
                    particle.Play();
                    break;
            }
        }
    }
    private static void UpdateMovePause(GameEntity entity, bool isPause)
    {
        if (!entity.hasMove)
            return;
        var move = entity.move;
        var pause = entity.pause;
        if (isPause)
        {
            pause.VelocityCache = move.Velocity;
            move.Velocity = Vector3.zero;
            move.Rigidbody.Sleep();
        }
        else
        {
            move.Velocity = pause.VelocityCache;
            move.Rigidbody.WakeUp();
        }
    }
    private static void UpdateTimelinePause(GameEntity entity, bool isPause)
    {
        if (!entity.hasTimeline)
            return;
        var timeline = entity.timeline;
        if (!timeline.IsRunning)
            return;
        timeline.IsPause = isPause;
        foreach (var clip in timeline.Timeline.Clips)
        {
            var clipReal = clip.Clip;
            if (clipReal.IsAlive)
            {
                clipReal.OnPause(isPause);
            }
        }
    }
    private static void UpdatePauseFix(GameEntity entity)
    {
        var pause = entity.pause;
        if (!pause.IsPause)
        {
            return;
        }
        UpdateEffectPauseFix(entity);
    }
    private static void UpdateEffectPauseFix(GameEntity entity)
    {
        if (!entity.hasView)
            return;
        var view = entity.view;
        foreach (var item in view.EffectObject)
        {
            var particle = item.GameObject.GetComponent();
            if (particle.time < 2f / GameConst.FPS)
            {
                particle.Play();
            }
            else
            {
                particle.Pause();
            }
        }
    }
}