using System;
using Godot;
using Microsoft.Extensions.Logging;
using OwofGames.AetherBind;
using OwofGames.GodotLume;
namespace GodotHostTest.AetherBind;
///
/// A node that provides injected services to other nodes.
///
[Icon("res://addons/AetherBind/ServiceSource.svg")]
public partial class ServiceSource : Node
{
private static readonly string RootScopeQualifiedName = typeof(RootScope).AssemblyQualifiedName!;
///
/// List of nodes that must be injected. This list will be automatically populated with all nodes in this object's
/// editor scene that have at least one [Inject] field or method.
///
[Export] protected Node?[] InjectedNodes = [];
///
/// Name of the scope for the services built by this service source.
///
[Export] private string _serviceScope = RootScopeQualifiedName;
///
/// Inject the required services in .
///
/// The service provider.
/// A callback method invoked with this scope's provider, if a scope was created.
internal void ResolveInjectedNodes(IProvider provider, Action? onScopeCreated)
{
var logger = provider.Get>();
// if this service source must also act as a scope, create the scope and use its service provider
if (_serviceScope != RootScopeQualifiedName)
{
// create the scoped provider
var serviceScope = ScopeTypesAndNames.GetType(_serviceScope);
provider = provider.GetScopedProvider(serviceScope);
// invoke onScopeCreated, if present
onScopeCreated?.Invoke(provider);
// invoke overridden callback
OnScopeCreated(provider);
}
else if (onScopeCreated != null)
{
logger.LogWarning("onScopeCreated passed during instantiation, but no scoped provider was created.");
}
// resolve the injected nodes against the chosen service provider
foreach (var node in InjectedNodes)
{
if (node == null) continue;
logger.LogTrace("Injecting {Node}.", node.Name);
if (node is IInjectable injectable)
{
injectable.Inject(provider);
}
}
}
// TODO: also add source generator to mark methods in derived classes with [OnScopeCreated] and perform parameter injection
///
/// This method is invoked as soon as the scope for the services is created, but before the services are injected into
/// the . Override this method in derived classes to perform custom initialization steps
/// for the services, like setting s.
///
/// Lume's service provider.
protected virtual void OnScopeCreated(IProvider serviceProvider)
{
}
}