// Oleg Petruny proprietary.

#include "InteractableHintWidgetManager.h"

#include "Blueprint/WidgetTree.h"
#include "Components/TextBlock.h"
#include "Components/VerticalBox.h"
#include "InputMappingContext.h"

#include "CommonFunctions.h"
#include "Interactable/Modificators/InteractableModificator.h"
#include "Widgets/InteractableHintWidget.h"


void UInteractableHintWidgetManager::Append(const UInteractableModificator* modificator)
{
    FScopeLock Lock(&hintsLock);

    if(!modificator)
    {
        hints->SetVisibility(ESlateVisibility::Visible);
        return;
    }

    if(hintsMap.Contains(modificator) || !modificator->GetMappingContext().IsValid())
        return;

    const auto& mappings = modificator->GetMappingContext().LoadSynchronous()->GetMappings();

    for(int32 i = hints->GetChildrenCount() - count - mappings.Num(); i < 0; ++i)
    {
        auto hint = WidgetTree->ConstructWidget<UInteractableHintWidget>(hintWidgetClass);
        hint->SetVisibility(ESlateVisibility::Hidden);
        hints->AddChild(hint);
    }

    int32 skipped = 0;
    for(int32 i = 0; i < mappings.Num(); ++i)
    {
        if(mappings[i].Action->ActionDescription.ToString().Equals("!hide!", ESearchCase::IgnoreCase))
        {
            ++skipped;
            continue;
        }

        auto hint = Cast<UInteractableHintWidget>(hints->GetChildAt(count++));
        hint->keyText->SetText(UCommonFunctions::GetKeyDisplayName(mappings[i].Key));
        hint->descriptionText->SetText(mappings[i].Action->ActionDescription);
        hint->SetVisibility(ESlateVisibility::Visible);
    }

    hintsMap.Add(modificator, { count - mappings.Num() + skipped, mappings.Num() - skipped });
}

void UInteractableHintWidgetManager::Remove(const UInteractableModificator* modificator)
{
    FScopeLock Lock(&hintsLock);

    if(!modificator)
    {
        hints->SetVisibility(ESlateVisibility::Hidden);
        return;
    }

    if(!hintsMap.Contains(modificator))
        return;

    auto& indexAndCount = hintsMap[modificator];
    for(int32 i = 0; i < indexAndCount.Value; ++i)
    {
        auto hint = hints->GetChildAt(indexAndCount.Key);
        hint->SetVisibility(ESlateVisibility::Hidden);
        hints->RemoveChildAt(indexAndCount.Key);
        hints->AddChild(hint);
        --count;
    }

    hintsMap.Remove(modificator);
}

void UInteractableHintWidgetManager::AnimateInteractionHint(const UInteractableModificator* modificator, const int32 index,
    const EInputAnimatedWidgetAnimation animation)
{
    FScopeLock Lock(&hintsLock);

    if(!hintsMap.Contains(modificator))
        return;

    auto& indexAndCount = hintsMap[modificator];
    auto hint = Cast<UInteractableHintWidget>(hints->GetChildAt(indexAndCount.Key + index));
    hint->RunAnimation(animation);
}