// Oleg Petruny proprietary.

#include "WorldDilationResponsiveUserWidget.h"

#include "Animation/UMGSequencePlayer.h"
#include "Animation/WidgetAnimation.h"
#include "Components/PanelWidget.h"

#include "CommonFunctions.h"

bool UWorldDilationResponsiveUserWidget::Initialize()
{
    UCommonFunctions::GetWorldDilationChangedDelegate().AddDynamic(this, &UWorldDilationResponsiveUserWidget::UpdateAnimations);

    return UUserWidget::Initialize();
}

void UWorldDilationResponsiveUserWidget::BeginDestroy()
{
    UCommonFunctions::GetWorldDilationChangedDelegate().RemoveDynamic(this, &UWorldDilationResponsiveUserWidget::UpdateAnimations);

    UUserWidget::BeginDestroy();
}

void UWorldDilationResponsiveUserWidget::UpdateAnimations(float newSpeed)
{
    UpdateAnimation(GetRootWidget(), newSpeed);

    if(auto root = Cast<UPanelWidget>(GetRootWidget()))
    {
        if(root->GetChildrenCount() == 0)
            return;

        // recursion would be simplier...
        TArray<int32> path{ 0 };
        UWidget* widget = root->GetChildAt(0);
        while(widget != root)
        {
            UpdateAnimation(widget, newSpeed);

            if(path.Num() < maxDepth)
            {
                if(auto panel = Cast<UPanelWidget>(widget))
                {
                    if(panel->GetChildrenCount())
                    {
                        path.Add(0);
                        widget = panel->GetChildAt(0);
                        continue;
                    }
                }
            }

            while(path.Num())
            {
                auto panel = widget->GetParent();
                int32& i = path[path.Num() - 1];
                if(++i < panel->GetChildrenCount())
                {
                    widget = panel->GetChildAt(i);
                    break;
                }
                else
                {
                    path.RemoveAt(path.Num() - 1, EAllowShrinking::No);
                    widget = panel;
                }
            }
        }
    }
}

void UWorldDilationResponsiveUserWidget::UpdateAnimation(UWidget* widget, float newSpeed)
{
    if(auto userWidget = Cast<UUserWidget>(widget))
    {
        for(auto player : userWidget->ActiveSequencePlayers)
            player->SetPlaybackSpeed(newSpeed);
    }
}
