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

namespace CommonAIClient.Unity.Battle
{
    public class DisplayCell : 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

        /// <summary>
        /// 主体上的挂载列表
        /// </summary>
        private HashMap<string, DisplayCell> mAttachParts = new HashMap<string, DisplayCell>();

        private bool mDisposed = false;
        private bool mActiveSelf;
        private GameObject mRootNode;
        private AssetObjectExt mModel;
        private Animation mAnimation;

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

        public bool IsDisposed { get { return mDisposed; } }
        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 AssetObjectExt Model
        {
            set
            {
                mModel = value;
                mModel.gameObject.ParentRoot(mRootNode);
                mAnimation = mModel.GetComponent<Animation>();
                PlayAnim(LastAnimName, LastCrossFade, LastWrapMode, LastSpeed);
            }
        }
        public bool ActiveSelf
        {
            get { return mActiveSelf; }
            set
            {
                this.mActiveSelf = value;
                this.mRootNode.SetActive(mActiveSelf);
            }
        }


        public DisplayCell(GameObject root, string name = "DisplayCell")
        {
            mRootNode = new GameObject(name);
            if (root != null)
            {
                mRootNode.ParentRoot(root);
            }
            s_alloc_count++;
            s_active_count++;
        }

        ~DisplayCell()
        {
            s_alloc_count--;
        }

        public DisplayCell AttachPart(string name, string dummy)
        {
            GameObject dummyNode = GetDummyNode(dummy);
            if (dummyNode == null)
            {
                dummyNode = mRootNode;
            }
            DisplayCell displayCell = BattleFactroy.Instance.CreateDisplayCell(dummyNode, name);
            mAttachParts.Add(name.ToLower(), displayCell);
            return displayCell;
        }

        public void DetachPart(string name)
        {
            DisplayCell displayCell = mAttachParts.RemoveByKey(name.ToLower());
            if (displayCell != null)
            {
                displayCell.Dispose();
            }
        }

        public virtual GameObject GetDummyNode(string name)
        {
            if (mModel == null || string.IsNullOrEmpty(name))
            {
                return null;
            }

            GameObject dummyNode = mModel.GetDummyNode(name);
            if (dummyNode == null)
            {
                foreach (var elem in mAttachParts)
                {
                    dummyNode = elem.Value.GetDummyNode(name);
                    if (dummyNode != null)
                        break;
                }
            }
            return dummyNode;
        }

        public float GetAnimCurrentTime()
        {
            if (!string.IsNullOrEmpty(mLastAnimName)
                && mAnimation != null)
            {
                AnimationState state = mAnimation[mLastAnimName];
                if (state != null)
                {
                    return state.time;
                }
            }
            return 0f;
        }

        public float GetAnimLength(string name)
        {
            if (!string.IsNullOrEmpty(name) && mAnimation != null 
                && mAnimation[name] != null)
            {
                return mAnimation[name].length;
            }
            return 0f;
        }

        public virtual void PlayAnim(string name, bool crossFade
            , WrapMode wrapMode = WrapMode.Once, float speed = 1f, float currentTime = 0f)
        {
            if (!string.IsNullOrEmpty(name))
            {
                foreach (var elem in mAttachParts)
                {
                    elem.Value.PlayAnim(name, crossFade, wrapMode, speed, currentTime);
                }

                mLastAnimName = name;
                mLastCrossFade = crossFade;
                mLastWrapMode = wrapMode;
                mLastSpeed = speed;

                if (mAnimation != null)
                {
                    AnimationState state = mAnimation[name];
                    if (state != null)
                    {
                        state.time = 0;
                        state.wrapMode = wrapMode;
                        state.speed = speed;
                        state.layer = 1;
                        state.time = currentTime;

                        if (crossFade)
                        {
                            mAnimation.CrossFade(name, 0.1f);
                        }
                        else
                        {
                            mAnimation.Play(name, PlayMode.StopAll);
                        }
                    }
                }

            }
        }

        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()
        {
            foreach (var elem in mAttachParts)
            {
                elem.Value.Dispose();
            }
            mAttachParts.Clear();

            BattleFactroy.Instance.GameObjectAdapter.Unload(mModel);
            GameObject.DestroyObject(mRootNode);
        }
    }
}