using Syntriax.Engine.Core.Abstract;

namespace Syntriax.Engine.Core;

public abstract class Behaviour : BehaviourBase
{
    private bool isInitializedThisFrame = false;

    protected IGameManager GameManager => BehaviourController.HierarchyObject.GameManager;
    protected IHierarchyObject HierarchyObject => BehaviourController.HierarchyObject;

    public Behaviour()
    {
        OnInitialized += OnInitialize;
        OnFinalized += OnFinalize;
        OnUnassigned += OnUnassign;
    }

    protected virtual void OnUnassign() { }
    protected virtual void OnUnassign(IAssignable assignable) => OnUnassign();

    protected virtual void OnInitialize() { }
    protected virtual void OnInitialize(IInitializable _)
    {
        isInitializedThisFrame = true;

        BehaviourController.OnPreUpdate += PreUpdate;
        BehaviourController.OnPreDraw += PreDraw;
        BehaviourController.OnUpdate += Update;
        BehaviourController.HierarchyObject.OnEnteredHierarchy += EnteredHierarchy;
        BehaviourController.HierarchyObject.OnExitedHierarchy += ExitedHierarchy;

        OnInitialize();

        if (HierarchyObject.IsInHierarchy)
            EnteredHierarchy(HierarchyObject, GameManager);
    }

    protected virtual void OnFinalize() { }
    protected virtual void OnFinalize(IInitializable _)
    {
        BehaviourController.OnPreUpdate -= PreUpdate;
        BehaviourController.OnPreDraw -= PreDraw;
        BehaviourController.OnUpdate -= Update;
        BehaviourController.HierarchyObject.OnEnteredHierarchy -= EnteredHierarchy;
        BehaviourController.HierarchyObject.OnExitedHierarchy -= ExitedHierarchy;

        OnFinalize();

        if (HierarchyObject.IsInHierarchy)
            ExitedHierarchy(HierarchyObject, GameManager);
    }

    protected virtual void OnPreUpdatePreActiveCheck() { }
    protected virtual void OnPreUpdate() { }
    protected virtual void PreUpdate(IBehaviourController _)
    {
        OnPreUpdatePreActiveCheck();

        if (!IsActive)
            return;

        if (isInitializedThisFrame)
            FirstActiveFrame();

        OnPreUpdate();
    }

    protected virtual void OnFirstActiveFrame() { }
    protected virtual void FirstActiveFrame()
    {
        OnFirstActiveFrame();
        isInitializedThisFrame = false;
    }

    protected virtual void OnUpdatePreActiveCheck() { }
    protected virtual void OnUpdate() { }
    protected virtual void Update(IBehaviourController _)
    {
        OnUpdatePreActiveCheck();

        if (!IsActive)
            return;

        OnUpdate();
    }

    protected virtual void OnPreDrawPreActiveCheck() { }
    protected virtual void OnPreDraw() { }
    protected virtual void PreDraw(IBehaviourController _)
    {
        OnPreDrawPreActiveCheck();

        if (!StateEnable.Enabled)
            return;

        OnPreDraw();
    }

    protected virtual void OnEnteredHierarchy(IGameManager gameManager) { }
    protected virtual void EnteredHierarchy(IHierarchyObject sender, IGameManager gameManager) => OnEnteredHierarchy(gameManager);

    protected virtual void OnExitedHierarchy(IGameManager gameManager) { }
    protected virtual void ExitedHierarchy(IHierarchyObject sender, IGameManager gameManager) => OnExitedHierarchy(gameManager);
}