using System;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;

namespace RebootKit.Engine.Foundation {
    public interface IController : IDisposable {
        UniTask OnStart(CancellationToken cancellationToken);
        void OnStop();
        void OnTick();
    }

    public class ControllersManager : IDisposable {
        private readonly List<IController> _controllers = new();
        private bool _isRunning;

        private readonly CancellationToken _cancellationToken;

        public ControllersManager(CancellationToken cancellationToken) {
            _cancellationToken = cancellationToken;
        }

        public void Dispose() {
            foreach (IController controller in _controllers) {
                controller.Dispose();
            }
        }

        public void Add(IController controller) {
            _controllers.Add(controller);

            if (_isRunning) {
                controller.OnStart(_cancellationToken);
            }
        }

        public void Remove(IController controller) {
            if (_isRunning) {
                controller.OnStop();
            }
            
            _controllers.Remove(controller);
        }

        public async UniTask Start(CancellationToken cancellationToken) {
            if (_isRunning) {
                return;
            }
            
            foreach (IController controller in _controllers) {
                await controller.OnStart(cancellationToken);
            }

            _isRunning = true;
        }

        public void Stop() {
            if (!_isRunning) {
                return;
            }
            
            foreach (IController controller in _controllers) {
                controller.OnStop();
            }

            _isRunning = false;
        }

        public void Tick() {
            foreach (IController controller in _controllers) {
                controller.OnTick();
            }
        }
    }

    public static class ControllersManagerUtils {
        public static void Add(this ControllersManager manager, ControllerAsset controllerAsset) {
            manager.Add(controllerAsset.Create());
        }

        public static void Add(this ControllersManager manager, List<ControllerAsset> controllerAsset) {
            foreach (ControllerAsset asset in controllerAsset) {
                manager.Add(asset.Create());
            }
        }

        public static void Add(this ControllersManager manager, ControllerAsset[] controllerAsset) {
            foreach (ControllerAsset asset in controllerAsset) {
                manager.Add(asset.Create());
            }
        }
    }
}