
namespace Guru
{
    using UnityEngine;
    using System;
    using System.Collections.Generic;
    
    
    public class Context : IContext, IEventPipeline, IDisposable
    {
        protected ContextObject _contextObj;
        private EventBus _eventBus;
        private Dictionary<string, IModel> _models;
        private Dictionary<string, IController> _controllers;
        private Dictionary<string, IResManager> _resManagers;
        private Dictionary<string, IHelper> _helpers;


        public static T Create<T> (string name = "") where T : Context, new()
        {
            var context = new T();
            context.Init();
            return context;
        }

        private void Init()
        {
            _contextObj = ContextObject.Create("guru_context");
            _contextObj.OnDestroyed = OnDestroyHandler;
            _contextObj.OnStart = OnStart;
            
            _eventBus = new EventBus();
            _models = new Dictionary<string, IModel>(10);
            _controllers = new Dictionary<string, IController>(10);
            _resManagers = new Dictionary<string, IResManager>(10);
            _helpers = new Dictionary<string, IHelper>(10);

            OnCreated();
        }

        protected virtual void OnCreated()
        {
              
        }

        protected virtual void OnStart()
        {
            
        }


        public virtual void Dispose()
        {
            
        }

        private void OnDestroyHandler()
        {
            OnDestroyed();
            Dispose();
        }

        protected virtual void OnDestroyed()
        {
            
        }

        #region 注册组件


        private static string GetInstanceName<T>(string instName = "")
        {
            if(string.IsNullOrEmpty(instName)) instName = nameof(T);
            return instName;
        }

        private bool TryAddUpdater(object obj)
        {
            if (obj is IUpdater a)
            {
                RegisterUpdater(a);
                return true;
            }
            return false;
        }

        public bool RegisterResManager<T>(T manager, string name = "") where T : IResManager, new()
        {
            TryAddUpdater(manager);
            if (_resManagers.TryAdd(GetInstanceName<T>(name), manager))
            {
                manager.Context = this;
                return true;
            }
            return false;
        }
        
        public T GetResManager<T>(string name = "") where T : IResManager, new()
        {
            return _resManagers.TryGetValue(GetInstanceName<T>(name), out var m) ? (T)m : default(T);
        }


        /// <summary>
        /// 注册数据模型
        /// </summary>
        /// <param instName="model"></param>
        /// <param name="name"></param>
        /// <typeparam instName="T"></typeparam>
        public bool RegisterModel<T>(T model, string name = "") where T : IModel, new()
        {
            TryAddUpdater(model);
            return _models.TryAdd(GetInstanceName<T>(name), model);
        }

        public T GetModel<T>(string name = "") where T : IModel, new()
        {
            return _models.TryGetValue(GetInstanceName<T>(name), out var m) ? (T)m : default(T);
        }
        
        /// <summary>
        /// 注册辅助工具
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="name"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public bool RegisterHelper<T>(T helper, string name = "") where T : IHelper, new()
        {
            TryAddUpdater(helper);
            return _helpers.TryAdd(GetInstanceName<T>(name), helper);
        }

        public T GetHelper<T>(string name = "") where T : IHelper, new()
        {
            return _helpers.TryGetValue(GetInstanceName<T>(name), out var m) ? (T)m : default(T);
        }

        /// <summary>
        /// 注册控制器
        /// </summary>
        /// <param instName="controller"></param>
        /// <typeparam instName="T"></typeparam>
        public bool RegisterController<T>(T controller, string name = "") where T : IController, new()
        {
            TryAddUpdater(controller);
            if (_controllers.TryAdd(GetInstanceName<T>(name), controller))
            {
                controller.Context = this;
                return true;
            }
            return false;
        }
        public T GetController<T>(string name = "") where T : IController, new()
        {
            return _controllers.TryGetValue(GetInstanceName<T>(name), out var c) ? (T)c : default(T);
        }
        #endregion

        #region 事件管理

        public void Subscribe<T>(Action<T> onReceiveMessage) where T : struct
        {
            _eventBus.Subscribe(onReceiveMessage);
        }

        public void Unsubscribe<T>(Action<T> onReceiveMessage) where T : struct
        {
            _eventBus.Unsubscribe(onReceiveMessage);
        }

        public void Send<T>(T message) where T : struct
        {
            _eventBus.Send(message);
        }
        
        #endregion

        #region 更新挂载

        
        public void RegisterUpdater(IUpdater updater)
        {
            _contextObj.AddUpdater(updater);
        }
        
        public void UnregisterUpdater(IUpdater updater)
        {
            _contextObj.RemoveUpdater(updater);
        }

        #endregion
    }
}