namespace Engine.Core.Internal;
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
/// 
/// This behaviour can be used for core managers like  etc. which need to be able to work even
/// in a very bare minimum setup without the presence of  to set themselves up on universe entrance.
/// I recommend not using this unless you know what you are doing but it might come in handy for some use cases.
/// 
public abstract class BehaviourIndependent : Behaviour
{
    private readonly Event.EventHandler delegateEnteredUniverse = null!;
    private readonly Event.EventHandler delegateExitedUniverse = null!;
    public BehaviourIndependent()
    {
        OnInitialized.AddListener(OnInitialize);
        OnFinalized.AddListener(OnFinalize);
        OnUnassigned.AddListener(OnUnassign);
        delegateEnteredUniverse = EnteredUniverse;
        delegateExitedUniverse = ExitedUniverse;
    }
    protected virtual void OnUnassign() { }
    protected void OnUnassign(IAssignable assignable) => OnUnassign();
    protected virtual void OnInitialize() { }
    protected void OnInitialize(IInitializable _)
    {
        BehaviourController.UniverseObject.OnEnteredUniverse.AddListener(delegateEnteredUniverse);
        BehaviourController.UniverseObject.OnExitedUniverse.AddListener(delegateExitedUniverse);
        OnInitialize();
        if (UniverseObject.IsInUniverse)
            EnteredUniverse(UniverseObject, new(Universe));
    }
    protected virtual void OnFinalize() { }
    protected void OnFinalize(IInitializable _)
    {
        BehaviourController.UniverseObject.OnEnteredUniverse.RemoveListener(delegateEnteredUniverse);
        BehaviourController.UniverseObject.OnExitedUniverse.RemoveListener(delegateExitedUniverse);
        OnFinalize();
        if (UniverseObject.IsInUniverse)
            ExitedUniverse(UniverseObject, new(Universe));
    }
    protected virtual void OnEnteredUniverse(IUniverse universe) { }
    protected void EnteredUniverse(IUniverseObject sender, IUniverseObject.EnteredUniverseArguments args) => OnEnteredUniverse(args.Universe);
    protected virtual void OnExitedUniverse(IUniverse universe) { }
    protected void ExitedUniverse(IUniverseObject sender, IUniverseObject.ExitedUniverseArguments args) => OnExitedUniverse(args.Universe);
}