using System;
using UnityEngine;
using XGame.Framework.Components;
using XGame.Framework.Interfaces;

namespace XGame.Framework.Map
{
    /// <summary>
    /// Entity实例
    /// </summary>
    /// <typeparam name="TViewModel"></typeparam>
    public abstract class EntityView<TViewModel> : IEntityView, IMapContextSetter, IEntityProxy, IDisposable where TViewModel : class, IEntityViewModel
    {
        private MapContext _context;
        protected MapContext Context => _context;

        private EntityBehaviour _behaviour;
        private TViewModel _viewModel;
        private ComponentGroup _componentGroup;
        protected ComponentGroup Group => _componentGroup;
        protected TViewModel VM => _viewModel;
        public Vector3 LocalPosition { get => _behaviour.transform.localPosition; set => _behaviour.transform.localPosition = value; }
        public Vector3 Position { get => _behaviour.transform.position; set => _behaviour.transform.position = value; }
        public Vector3 Rotation { get => _behaviour.transform.rotation.eulerAngles; set => _behaviour.transform.rotation = Quaternion.Euler(value); }
        protected bool IsInited { get; private set; }
        private void Init()
        {
            IsInited = true;
            _viewModel = Activator.CreateInstance<TViewModel>();
            (_viewModel as EntityViewModel)?.Init(_behaviour);
            if (_componentGroup == null)
            {
                _componentGroup = new ComponentGroup(this);
            }
            OnInited();
        }

        #region 接口实现

        public TComponent GetComponent<TComponent>(bool autoCreate = true) where TComponent : class, IComponent
        {
            var component = _componentGroup.Get<TComponent>();
            if (autoCreate && component == null)
            {
                component = Activator.CreateInstance<TComponent>();
                //component.Bind(this);
                _componentGroup.Add(component);
                if (Active && component is IActiveable activeable)
                { // EntityView处于激活状态，激活Component
                    activeable.Enable();
                }
            }
            return component;
        }

        MapContext IMapContextSetter.Context { set => _context = value; }
        EntityBehaviour IEntityProxy.Behaviour 
        { 
            get => _behaviour;
            set 
            {
                _behaviour = value; 
                Init();
            }
        }
        public bool Active { get; private set; }
        

        public void Enable(object intent)
        {
            if (Active) return;
            Active = true;
            _behaviour.gameObject.SetActive(true);
            _componentGroup.Enable(intent);
            OnEnable(intent);
        }


        public void Disable()
        {
            if (!Active) return;
            Active = false;
            _behaviour.gameObject.SetActive(false);
            _componentGroup.Disable();
            OnDisable();
        }
        void IDisposable.Dispose()
        {
            IsInited = false;
            OnDispose();
            _componentGroup.Dispose();
            (_viewModel as IDisposable)?.Dispose();
            _viewModel = null;
            _behaviour = null;
            _context = null;
        }
        public void Clear()
        {
            if (!IsInited) return;
            IsInited = false;
            OnDispose();
            _componentGroup.Clear();
            (_viewModel as IDisposable)?.Dispose();
            _viewModel = null;
            _behaviour = null;
            _context = null;
        }
        #endregion

        //protected abstract IEntityViewModel CtreatViewModel(IObjectCollector collector);

        protected abstract void OnEnable(object intent);

        protected abstract void OnDisable();
        protected virtual void OnInited()
        {

        }
        protected virtual void OnDispose()
        {
        }
    }
}