// Oleg Petruny proprietary.

#include "QuickTimeEventWidgetManager.h"

#include "Animation/UMGSequencePlayer.h"
#include "Animation/WidgetAnimation.h"
#include "Blueprint/WidgetTree.h"
#include "Components/CanvasPanel.h"
#include "Components/CanvasPanelSlot.h"
#include "Components/TextBlock.h"

#include "CommonFunctions.h"
#include "QuickTimeEvent.h"
#include "Widgets/QuickTimeEventWidget.h"

void UQuickTimeEventWidgetManager::ShowEvent(const int32 id, const struct FQuickTimeEventEnqueProperties& properties)
{
    FScopeLock Lock(&mappingLock);

    if(eventsMap.Contains(id) || !eventWidgetClasses.Contains(properties.type))
        return;

    auto eventWidget = WidgetTree->ConstructWidget<UQuickTimeEventWidget>(eventWidgetClasses[properties.type]);
    eventWidget->SetVisibility(ESlateVisibility::Hidden);
    eventWidget->keyText->SetText(UCommonFunctions::GetKeyDisplayName(properties.key));
    eventWidget->id = id;
    eventWidget->manager = this;
    eventWidget->duration = properties.duration;
    ((UCanvasPanelSlot*)canvas->AddChild(eventWidget))->SetAnchors({ (float)properties.anchor.X, (float)properties.anchor.Y });
    eventWidget->Show();

    eventsMap.Add(id, eventWidget);
}

EQuickTimeEventResult UQuickTimeEventWidgetManager::RemoveEvent(const int32 id)
{
    FScopeLock Lock(&mappingLock);

    if(!eventsMap.Contains(id))
        return EQuickTimeEventResult::FailedTime;

    UQuickTimeEventWidget* eventWidget;
    eventsMap.RemoveAndCopyValue(id, eventWidget);
    auto result = eventWidget->_ProcessBeforeRemoving();
    eventWidget->RemoveEvent();
    return result;
}

EQuickTimeEventResult UQuickTimeEventWidgetManager::AnimateEvent(const int32 id, const bool released)
{
    FScopeLock Lock(&mappingLock);

    if(!eventsMap.Contains(id))
        return EQuickTimeEventResult::FailedTime;

    return eventsMap[id]->_Process(released);
}

void UQuickTimeEventWidgetManager::UpdateAnimation(UWidget* widget, float newSpeed)
{
    if(auto eventWidget = Cast<UQuickTimeEventWidget>(widget))
    {
        for(auto player : eventWidget->ActiveSequencePlayers)
        {
            if(!player->GetAnimation()->GetName().Contains(TEXT("eventAnimation")))
                continue;

            newSpeed *= player->GetAnimation()->GetEndTime() / eventWidget->duration;
            player->SetPlaybackSpeed(newSpeed);
        }

        return;
    }

    Super::UpdateAnimation(widget, newSpeed);
}
