

namespace Guru
{
    using System;
    using System.Collections.Generic;
    using UnityEngine;

    public class ContextObject: MonoBehaviour
    {
        private const string InstanceName = "app_context";
        
        private HashSet<IUpdater> _updaters;
        private HashSet<IUpdater> _updatersWillRemove;
        
        public Action OnDestroyed;
        public Action OnStart;
        
        public static ContextObject Create(string name = "" )
        {
            if (string.IsNullOrEmpty(name)) name = InstanceName;
            var go = new GameObject(name);
            DontDestroyOnLoad(go);
            return go.AddComponent<ContextObject>();
        }

        public void AddUpdater(IUpdater updater)
        {
            _updaters.Add(updater);
        }

        public void RemoveUpdater(IUpdater updater)
        {
            updater.IsStopped = true;
            _updatersWillRemove.Add(updater);
        }


        #region 生命周期

        private void Awake()
        {
            _updaters = new HashSet<IUpdater>();
            _updatersWillRemove = new HashSet<IUpdater>();
        }

        void Start()
        {
            OnStart?.Invoke();
        }

        private void OnDestroy()
        {
            OnDestroyed?.Invoke();
        }
        
        public void SelfDestroy()
        {
            Destroy(gameObject);
        }

        private void Update()
        {
            if(_updaters.Count > 0)
            {
                foreach (var updater in _updaters)
                {
                    if(updater != null && 
                       !updater.IsStopped && 
                       !_updatersWillRemove.Contains(updater))
                    {
                        updater.OnUpdate();
                    }
                }

                if (_updatersWillRemove.Count > 0)
                {
                    foreach (var d in _updatersWillRemove)
                    {
                        _updaters.Remove(d);
                    }
                    _updatersWillRemove.Clear();
                }
            }
        }

        #endregion

    }
}