using UnityEngine;
using System;
using CommonLang.Concurrent;
using CommonAI.Zone;
using CommonLang;
using CommonAIClient.Unity.Utils;

namespace CommonAIClient.Unity.Battle
{
    public partial class BattleObject : IDisposable
    {
        #region RefCount

        private static AtomicInteger s_alloc_count = new AtomicInteger(0);
        private static AtomicInteger s_active_count = new AtomicInteger(0);

        /// <summary>
        /// 分配实例数量
        /// </summary>
        public static int AllocCount { get { return s_alloc_count.Value; } }
        /// <summary>
        /// 未释放实例数量
        /// </summary>
        public static int ActiveCount { get { return s_active_count.Value; } }

        #endregion

        private bool mDisposed;
        private bool mActiveSelf;
        private BattleScene mBattleScene;
        private GameObject mObjectRoot;
        private GameObject mDisplayRoot;
        private GameObject mDummyRoot;
        private GameObject mEffectRoot;
        private DisplayCell mDisplayCell;
        private HashMap<string, DummyNode> mDummys = new HashMap<string, DummyNode>();

        //保存最后申请的动作
        private string mLastAnimName;
        private bool mLastCrossFade;
        private WrapMode mLastWrapMode;
        private float mLastSpeed;

        public bool IsDisposed { get { return mDisposed; } }
        protected BattleScene BattleScene { get { return mBattleScene; } }
        protected GameObject ObjectRoot { get { return mObjectRoot; } }
        public Vector3 Position { get { return this.mObjectRoot.Position(); } }
        protected GameObject DisplayRoot { get { return mDisplayRoot; } }
        protected GameObject DummyRoot { get { return mDummyRoot; } }
        public GameObject EffectRoot { get { return mEffectRoot; } }
        protected DisplayCell DisplayCell { get { return mDisplayCell; } }
        protected HashMap<string, DummyNode> Dummys { get { return mDummys; } }
        public string LastAnimName { get { return mLastAnimName; } }
        public bool LastCrossFade { get { return mLastCrossFade; } }
        public WrapMode LastWrapMode { get { return mLastWrapMode; } }
        public float LastSpeed { get { return mLastSpeed; } }
        public bool ActiveSelf
        {
            get { return mActiveSelf; }
            set
            {
                this.mActiveSelf = value;
                this.ObjectRoot.SetActive(mActiveSelf);
                this.PlayAnim(mLastAnimName, mLastCrossFade, mLastWrapMode, mLastSpeed);
            }
        }


        public BattleObject(BattleScene battleScene, string name = "")
        {
            s_alloc_count++;
            s_active_count++;

            mBattleScene = battleScene;
            mObjectRoot = new GameObject(name);

            mDisplayRoot = new GameObject("DisplayRoot");
            mDisplayRoot.ParentRoot(mObjectRoot);

            mDummyRoot = new GameObject("DummyRoot");
            mDummyRoot.ParentRoot(mObjectRoot);

            mEffectRoot = new GameObject("EffectRoot");
            mEffectRoot.ParentRoot(mObjectRoot);

            mDisplayCell = BattleFactroy.Instance.CreateDisplayCell(mDisplayRoot);
        }

        ~BattleObject()
        {
            s_alloc_count--;
        }

        protected virtual void CorrectDummyNode()
        {
            foreach (var elem in mDummys)
            {
                GameObject trace = mDisplayCell.GetDummyNode(elem.Key);
                elem.Value.Init(elem.Key, trace);
            }
        }

        /// <summary>
        /// 如果名字不为空 一定会返回一个DummyNode
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public virtual DummyNode GetDummyNode(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                Debug.LogError("string.IsNullOrEmpty(name)");
                return null;
            }

            DummyNode dummyNode = null;
            if (!mDummys.TryGetValue(name, out dummyNode))
            {
                GameObject node = mDisplayCell.GetDummyNode(name);
                if (node == null)
                {
                    Debug.LogError("node not exist " + name);
                }
                GameObject tmp = new GameObject(name);
                tmp.ParentRoot(mDummyRoot);
                dummyNode = tmp.AddComponent<DummyNode>();
                dummyNode.Init(name, node);
                mDummys.Add(name, dummyNode);
            }
            return dummyNode;
        }

        public virtual float GetAnimLength(string name)
        {
            if (this.DisplayCell != null)
            {
                return this.DisplayCell.GetAnimLength(name);
            }
            return 0f;
        }

        public virtual void PlayAnim(string name, bool crossFade
            , WrapMode wrapMode = WrapMode.Once, float speed = 1f)
        {
            if (!string.IsNullOrEmpty(name))
            {
                mLastAnimName = name;
                mLastCrossFade = crossFade;
                mLastWrapMode = wrapMode;
                mLastSpeed = speed;
                mDisplayCell.PlayAnim(name, crossFade, wrapMode, speed);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="eff"></param>
        /// <param name="pos"> unity pos</param>
        /// <param name="rot"> unity rot</param>
        public virtual void PlayEffect(LaunchEffect eff, Vector3 pos, Quaternion rot)
        {
            if (eff != null)
            {
                //声音
                if (!string.IsNullOrEmpty(eff.SoundName))
                {
                    if (eff.IsLoop)
                    {
                        BattleFactroy.Instance.SoundAdapter.PlaySound(eff.SoundName, eff.EffectTimeMS, pos);
                    }
                    else
                    {
                        BattleFactroy.Instance.SoundAdapter.PlaySound(eff.SoundName, pos);
                    }
                }
                //特效
                if (!string.IsNullOrEmpty(eff.Name))
                {
                    BattleFactroy.Instance.GameObjectAdapter.Load(eff.Name
                           , System.IO.Path.GetFileNameWithoutExtension(eff.Name)
                           , (succ, aoe) =>
                           {
                               if (succ)
                               {
                                   if (IsDisposed && eff.BindBody)
                                   {
                                       BattleFactroy.Instance.GameObjectAdapter.Unload(aoe);
                                       return;
                                   }

                                   OnLoadEffectSuccess(aoe, eff, pos, rot);
                               }
                           });
                }
            }
        }

        protected virtual void OnLoadEffectSuccess(AssetObjectExt aoe
            , LaunchEffect eff, Vector3 pos, Quaternion rot)
        {
            aoe.gameObject.Parent(BattleScene.EffectRoot);
            aoe.gameObject.Position(pos);
            aoe.gameObject.Rotation(rot);

            var script = aoe.gameObject.AddComponent<EffectAutoDestroy>();
            script.aoeHandler = aoe;
            script.duration = eff.IsLoop ? eff.EffectTimeMS / 1000f : 0f;

            GameObject dummy = mEffectRoot;
            if (!string.IsNullOrEmpty(eff.BindPartName))
            {
                dummy = mDisplayCell.GetDummyNode(eff.BindPartName);
                if (dummy == null)
                {
                    dummy = mEffectRoot;
                }

                aoe.gameObject.Position(dummy.Position());
            }

            if (eff.BindBody)
            {
                aoe.gameObject.ParentRoot(dummy);
            }
        }

        public void Update(float deltaTime)
        {
            if (!mDisposed)
            {
                OnUpdate(deltaTime);
            }
        }

        protected virtual void OnUpdate(float deltaTime)
        {
        }

        public void Dispose()
        {
            if (!mDisposed)
            {
                OnDispose();
                mDisposed = true;
                s_active_count--;
            }
        }

        protected virtual void OnDispose()
        {
            mDisplayCell.Dispose();
            AssetObjectExt[] aoes = mDummyRoot.GetComponentsInChildren<AssetObjectExt>();
            foreach (var elem in aoes)
            {
                EffectAutoDestroy[] scripts = elem.gameObject.GetComponents<EffectAutoDestroy>();
                if (scripts.Length > 0)
                {
                    foreach (var script in scripts)
                    {
                        script.DoDestroy();
                    }
                }
                else
                {
                    BattleFactroy.Instance.GameObjectAdapter.Unload(elem);
                }
            }
            GameObject.Destroy(mObjectRoot);
        }
    }
}