using System;
using System.Collections.Generic;
using XGame.Framework.Interfaces;

namespace XGame.Framework.Components
{
    public class ComponentGroup : IComponentGroup
    {
        private Dictionary<Type, IComponent> _components;
        private List<IUpdate> _updates;
        private List<ILateUpdate> _lateUpdates;
        private object _context;
        public ComponentGroup(object context)
        {
            _context = context;
            _components = new Dictionary<Type, IComponent>();
            _updates = new List<IUpdate>();
            _lateUpdates = new List<ILateUpdate>();
        }
        public void Add(IComponent component)
        {
            if (component == null) return;
            _components.Add(component.GetType(), component);
            component.Bind(_context);
            if (component is IUpdate update)
            {
                _updates.Add(update);
            }
            if (component is ILateUpdate lateUpdate)
            {
                _lateUpdates.Add(lateUpdate);
            }
        }
        public void Remove(IComponent component)
        {
            if (component == null) return;
            _components.Remove(component.GetType());
            if (component is IUpdate update)
            {
                _updates.Remove(update);
            }
            if (component is ILateUpdate lateUpdate)
            {
                _lateUpdates.Remove(lateUpdate);
            }
        }
        public TComponent Get<TComponent>() where TComponent : IComponent
        {
            if (_components.TryGetValue(typeof(TComponent), out var component))
            {
                return (TComponent)component;
            }
            return default;
        }
        public void Enable(object intent)
        {
            foreach (var component in _components.Values)
            {
                if (component is IActiveable impl)
                {
                    impl.Enable(intent);
                }
            }
        }
        public void Disable()
        {
            foreach (var component in _components.Values)
            {
                if (component is IActiveable impl)
                {
                    impl.Disable();
                }
            }
        }
        public void Update(int millisecond)
        {
            foreach (var update in _updates)
            {
                update?.Update(millisecond);
            }
        }
        public void LateUpdate(int millisecond)
        {
            foreach (var lateUpdate in _lateUpdates)
            {
                lateUpdate?.LateUpdate(millisecond);
            }
        }
        public void Reset()
        {
            foreach (var component in _components.Values)
            {
                (component as IReset)?.Reset();
            }
        }
        public void Clear()
        {
            foreach (var component in _components.Values)
            {
                (component as IReference)?.Clear();
            }
        }
        public void Dispose()
        {
            foreach (var component in _components.Values)
            {
                (component as IDisposable)?.Dispose();
            }
            _components.Clear();
        }
    }
}
