using System;
using FairyGUI;
using UnityEngine;
using Spine.Unity;
using BingoBrain.Core;

namespace BingoBrain
{
    public class JEffectUI : BaseUI
    {
        private JEffectUICtrl ctrl;
        private JEffectModel model;
        private FGUI.JFx.com_FX ui;

        private Transform parTrf;

        public JEffectUI(JEffectUICtrl ctrl) : base(ctrl)
        {
            uiName = UIConst.JEffectUI;
            this.ctrl = ctrl;
        }

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

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

        private void DoSomething(FxPlayData data, Transform trf, GameObject arg, Action recFx)
        {
            trf.SetParent(parTrf);
            arg.SetLayer("UI");
            var cb = SetSortingOrder(arg);
            data.endEvent += (e) => cb?.Invoke();

            var startPot = GameHelper.FguiToUnityLocalPot(data.startPot);

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

            IsfvKit.StartAction("1", () =>
            {
                data.endEvent?.Invoke(arg);


                recFx?.Invoke();

                FxPlayData.Release(data);
            }, data.duration);
        }

        private Action SetSortingOrder(GameObject obj)
        {
            Action action = null;
            var renders = obj.GetComponentsInChildren<Renderer>();
            foreach (var render in renders)
            {
                if (render == null)
                {
                    continue;
                }

                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 FGUI.JFx.com_FX;
        }

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

        protected override void OnOpen(object args)
        {
        }

        #endregion
    }

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

        public static FxPlayData Get(Fx_Type fx_Type, float _duration, Vector2 _pot)
        {
            var 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;
    }
}