using Cysharp.Threading.Tasks;
using DG.Tweening;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

namespace WS
{
    [ObjectSystem]
    public class AnimatorComponentAwakeSystem : AwakeSystem<AnimatorComponent, Animator, Animator>
    {
        public override void Awake(AnimatorComponent self, Animator ani, Animator answerAni)
        {
            self.Awake(ani, answerAni);
        }
    }
    [ObjectSystem]
    public class SingleAnimatorComponentAwakeSystem : AwakeSystem<AnimatorComponent, Animator>
    {
        public override void Awake(AnimatorComponent self, Animator ani)
        {
            self.Awake(ani);
        }
    }
    [ObjectSystem]
    public class AnimatorComponentUpdateSystem : UpdateSystem<AnimatorComponent>
    {
        public override void Update(AnimatorComponent self)
        {
            self.Update();
        }
    }
    public class AnimatorComponent : WSComponent
    {
        ///<summary></summary>
        private string objName;
        ///<summary>动画组件</summary>
        private Animator Anim;
        ///<summary>关联物体动画组件</summary>
        private Animator AnswerAnim;
        /////<summary>关联物体动画组件</summary>
        //private List<Animator> answerAnimList;
        ///<summary>回调</summary>
        private UnityAction OnCallback;
        ///<summary>动画剪辑名称</summary>
        private string clipName=null;
        ///<summary>动画剪辑名称</summary>
        private string answerClipName=null;

        private List<AnswerObjData> answerObjList= new List<AnswerObjData>();

        ///<summary>并行播放</summary>
        private bool IsParallel;
        ///<summary>播放</summary>
        private bool isplay;

        public void Awake(Animator anim)
        {
            Anim = anim;
        }
        public void Awake(Animator anim, Animator answerAnim)
        {
            Anim = anim;
            AnswerAnim = answerAnim;
        }

        public void InitInteractAnim(string interactObjName, string animName)
        {
            objName = interactObjName;
            clipName = animName;
            Anim = GameObject.Find(objName).GetComponent<Animator>();
        }
        public void InitAnswerAnim(List<AnswerObjData> answerList)
        {
            answerObjList = answerList;
        }

        /// <summary>播放动画</summary>
        public void PlaySync(Animator animator, string animName)
        {
            if (!animator.gameObject.activeSelf)
            {
                Log.LogError($"{animator.gameObject.name}未启用");
                return;
            }
            animator.Play(animName);
            animator.speed = 1;
        }
        /// <summary>播放动画</summary>
        public async UniTask PlayAsync(Animator animator, string animName)
        {
            if (!animator.gameObject.activeSelf)
            {
                Log.LogError($"{animator.gameObject.name}未启用");
                return;
            }
            animator.Play(animName);
            animator.speed = 1;
            var infos = animator.runtimeAnimatorController.animationClips;
            for (int j = 0; j < infos.Length; j++)
            {
                var info = infos[j];
                if (info.name == animName)
                {
                    await TimerComponent.Instance.WaitAsync(info.length);
                    return;
                }
            }
        }
        /// <summary>播放关联动画</summary>
        /// <param name="name">名称</param>
        /// <param name="action">回调</param>
        public async UniTask PlayAnimSerial(UnityAction action)
        {
            try
            {
                if (Anim != null)
                {
                    await PlayAsync(Anim, clipName);
                    SceneDataSaveComponent.Instance.AddSceneData(SceneComponent.Instance.ThisScene, objName, clipName);
                }
                for (int i = 0; i < answerObjList.Count; i++)
                {
                    string answerName = answerObjList[i].AnswerName;
                    string animName = answerObjList[i].AnswerAnimName;
                    Animator animator = GameObject.Find(answerName).GetComponent<Animator>();

                    await PlayAsync(animator, animName);
                    //Debug.Log(i + "****" + answerObjList.Count);
                    //Debug.Log(answerObjList[i].AnswerAnimName);
                    SceneDataSaveComponent.Instance.AddSceneData(SceneComponent.Instance.ThisScene, answerName, animName);
                }
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
            action?.Invoke();
        }
        /// <summary>同时播放动画</summary>
        public async void PlayAnimParallel(UnityAction action)
        {
            float time = 0;
            if (Anim != null)
            {

                PlaySync(Anim, clipName);
                var clips = Anim.runtimeAnimatorController.animationClips;
                for (int j = 0; j < clips.Length; j++)
                {
                    var info = clips[j];
                    if (info.name == clipName && info.length > time)
                    {
                        time = info.length;
                    }
                }
                SceneDataSaveComponent.Instance.AddSceneData(SceneComponent.Instance.ThisScene, objName, clipName);
            }
            for (int i = 0; i < answerObjList.Count; i++)
            {
                Animator animator = GameObject.Find(answerObjList[i].AnswerName).GetComponent<Animator>();
                string animName = answerObjList[i].AnswerAnimName;
                PlaySync(animator, animName);

                var clips = animator.runtimeAnimatorController.animationClips;
                for (int j = 0; j < clips.Length; j++)
                {
                    var info = clips[j];
                    if (info.name == animName && info.length > time)
                    {
                        time = info.length;
                    }
                }
                SceneDataSaveComponent.Instance.AddSceneData(SceneComponent.Instance.ThisScene, answerObjList[i].AnswerName, answerObjList[i].AnswerAnimName);
            }
            await TimerComponent.Instance.WaitAsync(time);
            action?.Invoke();
        }

        /// <summary>播放动画</summary>
        /// <param name="name">名称</param>
        /// <param name="action">回调</param>
        public void PlayAnim(string name, UnityAction action)
        {
            clipName = name;
            Anim.Play(name);
            Anim.speed = 1;
            OnCallback = action;
            isplay = true;
        }
        /// <summary>同时播放动画</summary>
        /// <param name="name">交互物体动画</param>
        /// <param name="answerAni">响应物体动画</param>
        /// <param name="isParallel">是否并行播放动画</param>
        /// <param name="action">回调</param>
        public void PlayAnim(string name, string answerAni, bool isParallel, UnityAction action)
        {
            IsParallel = isParallel;
            clipName = name;
            answerClipName = answerAni;
            Anim.Play(name);
            Anim.speed = 1;
            if (isParallel)
            {
                AnswerAnim.Play(answerAni);
                AnswerAnim.speed = 1;
            }
            OnCallback = action;
            isplay = true;
        }
        public void Update()
        {
            if (Anim != null)
            {
                if (isplay)
                {
                    AnimatorStateInfo stateInfo = Anim.GetCurrentAnimatorStateInfo(0);
                    if (stateInfo.IsName(clipName))
                    {
                        if (stateInfo.normalizedTime >= 1f)
                        {
                            if (!IsParallel && AnswerAnim != null)
                            {
                                AnimatorStateInfo stateInfoAnswer = AnswerAnim.GetCurrentAnimatorStateInfo(0);
                                if (!stateInfoAnswer.IsName(answerClipName))
                                {
                                    AnswerAnim.Play(answerClipName);
                                    AnswerAnim.speed = 1;
                                }
                                if (stateInfoAnswer.IsName(answerClipName))
                                {
                                    if (stateInfoAnswer.normalizedTime == 0f)
                                    {
                                        AnswerAnim.Play(answerClipName);
                                        AnswerAnim.speed = 1;
                                    }
                                    if (stateInfoAnswer.normalizedTime >= 1f)
                                    {
                                        OnCallback?.Invoke();
                                        isplay = false;
                                    }
                                }
                            }
                            else
                            {
                                OnCallback?.Invoke();
                                isplay = false;
                            }
                        }
                    }
                }
            }
        }

        public override void Dispose()
        {
            base.Dispose();
            Anim = null;
            answerObjList.Clear();
            AnswerAnim = null;
            OnCallback = null;
        }
    }
}
