using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
namespace Bootstrap
{
///
/// A service that provides information about the boot completion status
/// and allows systems to register for callbacks when boot is complete.
///
public static class BootCompletionService
{
///
/// True if the boot process has fully completed
///
public static bool IsBootComplete { get; private set; }
///
/// Timestamp when the boot completed (Time.realtimeSinceStartup)
///
public static float BootCompletionTime { get; private set; }
///
/// Event triggered when boot process completes.
/// Will be triggered immediately for new subscribers if boot is already complete.
///
public static event Action OnBootComplete;
///
/// Actions to be executed in a specific order once boot completes
///
private static readonly List _orderedInitActions = new List();
///
/// Task completion source for async boot completion waiting
///
private static TaskCompletionSource _bootCompletionTask;
///
/// Initialize the service - called by CustomBoot
///
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
private static void Initialize()
{
// Reset state
IsBootComplete = false;
_bootCompletionTask = new TaskCompletionSource();
// Subscribe to CustomBoot completion event
CustomBoot.OnBootCompleted += HandleBootCompleted;
Debug.Log("[BootCompletionService] Initialized and waiting for boot completion");
}
///
/// Handler for when CustomBoot reports completion
///
private static void HandleBootCompleted()
{
if (IsBootComplete) return; // Avoid duplicate triggers
IsBootComplete = true;
BootCompletionTime = Time.realtimeSinceStartup;
Debug.Log($"[BootCompletionService] Boot completed at {BootCompletionTime:F2}s since startup");
// Execute ordered initialization actions
ExecuteOrderedInitActions();
// Complete the task
_bootCompletionTask.TrySetResult(true);
// Trigger the event
OnBootComplete?.Invoke();
}
///
/// Execute the registered ordered initialization actions
///
private static void ExecuteOrderedInitActions()
{
// Sort actions by priority
_orderedInitActions.Sort((a, b) => a.Priority.CompareTo(b.Priority));
foreach (var action in _orderedInitActions)
{
try
{
Debug.Log($"[BootCompletionService] Executing priority {action.Priority} initialization: {action.Name}");
action.Action?.Invoke();
}
catch (Exception e)
{
Debug.LogError($"[BootCompletionService] Error executing initialization action '{action.Name}': {e.Message}\n{e.StackTrace}");
}
}
// Clear the list after execution
_orderedInitActions.Clear();
}
///
/// Register an action to be executed when boot is complete.
/// If boot is already complete, the action will execute immediately.
///
/// The action to execute
/// Lower numbers execute first (default: 100)
/// Optional name for debugging
public static void RegisterInitAction(Action action, int priority = 100, string name = null)
{
if (action == null) return;
name = name ?? $"Anonymous_{_orderedInitActions.Count}";
if (IsBootComplete)
{
// Boot already completed, execute immediately
Debug.Log($"[BootCompletionService] Executing late initialization: {name} (boot already complete)");
try
{
action.Invoke();
}
catch (Exception e)
{
Debug.LogError($"[BootCompletionService] Error executing late initialization action '{name}': {e.Message}\n{e.StackTrace}");
}
}
else
{
// Add to ordered list
_orderedInitActions.Add(new OrderedInitAction
{
Action = action,
Priority = priority,
Name = name
});
Debug.Log($"[BootCompletionService] Registered initialization action: {name} with priority {priority}");
}
}
///
/// Returns a task that completes when the boot process is complete.
/// If boot is already complete, returns a completed task.
///
public static Task WaitForBootCompletionAsync()
{
if (IsBootComplete)
{
return Task.CompletedTask;
}
return _bootCompletionTask.Task;
}
///
/// Structure for ordered initialization actions
///
private class OrderedInitAction
{
public Action Action;
public int Priority;
public string Name;
}
}
}