using System;
using DG.Tweening;
using FairyGUI;
using FGUI.Fx_502;
using Spine.Unity;
using UnityEngine;

namespace ChillConnect
{
    public class FXWndUI : BaseUI
    {
        private FXWndUICtrl ctrl;
        private FXWndModel model;
        private com_FX ui;

        private Transform parTrf;

        public FXWndUI(FXWndUICtrl ctrl) : base(ctrl)
        {
            uiName = UIConst.FXWndUI;
            this.ctrl = ctrl;
        }

        protected override void SetUIInfo(UIInfo uiInfo)
        {
            uiInfo.packageName = "Fx_502";
            uiInfo.assetName = "com_FX";
            uiInfo.layerType = UILayerType.Animation;
        }

        public void PlayFx(FxPlayData fxPlayData)
        {
            FxPlayData data = fxPlayData;
            GameObject arg = null;
            Transform trf = null;
            Action recFx = null;
            if (data.isParticleSystem)
            {
                ParticleSystem system = FXManager.Instance.GetFx<ParticleSystem>(data.fxType);
                system.Play();
                arg = system.gameObject;
                trf = system.transform;
                recFx = delegate { FXManager.Instance.RecFx(data.fxType, system); };
            }
            else
            {
                SkeletonAnimation system = FXManager.Instance.GetFx<SkeletonAnimation>(data.fxType);
                trf = system.transform;
                arg = system.gameObject;
                recFx = delegate { FXManager.Instance.RecFx(data.fxType, system); };
            }

            trf.SetParent(parTrf);
            arg.SetLayer("UI");
            Action cb = SetSortingOrder(arg);
            data.endEvent += e => cb?.Invoke();

            Vector3 startPot = GameHelper.FguiPotToUnityTrfLocalPot(data.startPot);

            trf.localPosition = startPot;
            trf.localScale = Vector3.one * data.size;
            trf.localEulerAngles = Vector3.zero;
            fxPlayData.startEvent?.Invoke(arg);

            DOVirtual.DelayedCall(data.duration, () =>
            {
                data.endEvent?.Invoke(arg);


                recFx?.Invoke();

                FxPlayData.Release(data);
            });
        }

        private Action SetSortingOrder(GameObject obj)
        {
            Action action = null;
            Renderer[] renders = obj.GetComponentsInChildren<Renderer>();
            foreach (Renderer render in renders)
            {
                if (render != null)
                {
                    render.sortingOrder += 300;
                    action += () => { render.sortingOrder -= 300; };
                }
            }

            return action;
        }

        #region 生命周期

        protected override void OnInit()
        {
        }

        protected override void OnClose()
        {
        }

        protected override void OnBind()
        {
            ui = baseUI as com_FX;
        }

        protected override void OnOpenBefore(object args)
        {
            parTrf = ui.displayObject.cachedTransform;
        }

        protected override void OnOpen(object args)
        {
        }

        protected override void OnHide()
        {
        }

        protected override void OnDisplay(object args)
        {
        }

        #endregion

        #region 消息

        protected override void AddListener()
        {
        }

        protected override void RemoveListener()
        {
        }

        #endregion
    }

    public class FxPlayData
    {
        private static ObjectPool<FxPlayData> _Pool = new ObjectPool<FxPlayData>();

        public static FxPlayData Get(Fx_Type fx_Type, float _duration, Vector2 _pot)
        {
            FxPlayData data = _Pool.Get();
            if (_pot == Vector2.zero)
            {
                data.startPot = GRoot.inst.size / 2;
            }
            else
            {
                data.startPot = _pot;
            }

            if (_duration == 0)
            {
                data.duration = 1;
            }
            else
            {
                data.duration = _duration;
            }

            data.fxType = fx_Type;
            return data;
        }

        public static void Release(FxPlayData data)
        {
            data.duration = 0;
            data.startEvent = null;
            data.endEvent = null;
            data.isParticleSystem = true;
            data.startPot = Vector2.zero;
            _Pool.Release(data);
        }

        public float duration;

        public Fx_Type fxType;

        public bool isParticleSystem = true;

        public Vector2 startPot;

        public Action<GameObject> startEvent;

        public Action<GameObject> endEvent;

        public int size = 100;
    }
}