using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SilkroadBot.Core.Configuration;
using SilkroadBot.Core.Events;
using SilkroadBot.Core.Plugins;
using SilkroadBot.Core.State;
using SilkroadBot.Plugins.SDK.Interfaces;
namespace SilkroadBot.Core.Services;
///
/// Central service container and orchestrator for the bot framework.
/// Manages DI, service registration, and bot instance lifecycle.
///
public class BotEngine : IDisposable
{
private readonly IServiceProvider _services;
private readonly ILogger _logger;
private readonly Dictionary _activeBots = new();
private readonly ProtocolAdapterRegistry _adapterRegistry;
private readonly PluginManager _pluginManager;
public IReadOnlyDictionary ActiveBots => _activeBots;
public ProtocolAdapterRegistry AdapterRegistry => _adapterRegistry;
public PluginManager PluginManager => _pluginManager;
public IEventDispatcher EventDispatcher { get; }
public BotEngine(IServiceProvider services)
{
_services = services;
_logger = services.GetRequiredService>();
_adapterRegistry = services.GetRequiredService();
_pluginManager = services.GetRequiredService();
EventDispatcher = services.GetRequiredService();
}
///
/// Create a new bot instance for a profile.
///
public BotContext CreateBot(string profileId, Domain.Enums.GameClientType clientType)
{
var adapter = _adapterRegistry.GetAdapter(clientType);
var eventDispatcher = new EventDispatcher();
var logger = _services.GetRequiredService().CreateLogger();
var bot = new BotContext(profileId, adapter, eventDispatcher, logger);
_activeBots[profileId] = bot;
_logger.LogInformation("Created bot for profile {ProfileId} with {ClientType}", profileId, clientType);
return bot;
}
///
/// Remove and dispose a bot instance.
///
public async Task RemoveBotAsync(string profileId)
{
if (_activeBots.TryGetValue(profileId, out var bot))
{
await bot.DisconnectAsync();
bot.Dispose();
_activeBots.Remove(profileId);
_logger.LogInformation("Removed bot for profile {ProfileId}", profileId);
}
}
///
/// Initialize the plugin system and load all available plugins.
///
public async Task InitializePluginsAsync(IPluginContext context)
{
await _pluginManager.DiscoverAndLoadAsync(context);
}
///
/// Configure services for the bot engine via DI.
///
public static IServiceCollection ConfigureServices(IServiceCollection services, string pluginDir)
{
services.AddSingleton();
services.AddSingleton();
services.AddSingleton(sp => new PluginManager(
pluginDir,
sp,
sp.GetRequiredService>()
));
services.AddSingleton();
services.AddLogging(builder => builder.AddConsole().SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug));
return services;
}
public void Dispose()
{
foreach (var bot in _activeBots.Values)
bot.Dispose();
_activeBots.Clear();
_pluginManager.Dispose();
}
}