// Oleg Petruny proprietary.

#include "WidgetsManager.h"

#include "Blueprint/UserWidget.h"
#include "Components/TextBlock.h"
#include "Engine/World.h"
#include "InputMappingContext.h"
#include "Kismet/GameplayStatics.h"
#include "UObject/ScriptInterface.h"

#include "CustomGameInstance.h"
#include "Interactable/Interactable.h"
#include "Interactable/Modificators/InteractableModificator.h"
#include "Interactable/Modificators/InventoryInteractableModificator.h"
#include "PlayerBase.h"
#include "Widgets/CutsceneSkipWidget.h"
#include "Widgets/DialogueRowWidgetManager.h"
#include "Widgets/DialogueSkipWidget.h"
#include "Widgets/InteractableHintWidgetManager.h"
#include "Widgets/InventoryWidget.h"
#include "Widgets/JournalWidget.h"
#include "Widgets/MainMenu/MainMenuWidget.h"
#include "Widgets/QuickTimeEventWidgetManager.h"

void UWidgetsManager::Init()
{
    if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0))
    {
        for(auto& widget : permaOverlayWidgets)
        {
            if(auto instance = CreateWidget<UUserWidget>(PC, widget))
            {
                permaOverlayWidgetsInstances.Add(instance);
                instance->AddToViewport();
            }
        }
        for(auto& widget : overlayWidgets)
        {
            if(auto instance = CreateWidget<UUserWidget>(PC, widget))
            {
                overlayWidgetsInstances.Add(instance);
                instance->AddToViewport();
            }
        }
        if(auto instance = CreateWidget<UMainMenuWidget>(PC, mainMenuWidgetClass))
        {
            mainMenuWidget = instance;
            mainMenuWidget->SetVisibility(ESlateVisibility::Hidden);
            mainMenuWidget->AddToViewport(8);
        }
        if(auto instance = CreateWidget<UInteractableHintWidgetManager>(PC, interactableHintWidgetManagerClass))
        {
            interactableHintWidgetManager = instance;
            interactableHintWidgetManager->SetVisibility(ESlateVisibility::Visible);
            interactableHintWidgetManager->AddToViewport();
        }
        if(auto instance = CreateWidget<UCutsceneSkipWidget>(PC, cutsceneSkipWidgetClass))
        {
            cutsceneSkipWidget = instance;
            cutsceneSkipWidget->SetVisibility(ESlateVisibility::Hidden);
            cutsceneSkipWidget->AddToViewport();
        }
        if(auto instance = CreateWidget<UQuickTimeEventWidgetManager>(PC, quickTimeEventWidgetManagerClass))
        {
            quickTimeEventWidgetManager = instance;
            quickTimeEventWidgetManager->SetVisibility(ESlateVisibility::Visible);
            quickTimeEventWidgetManager->AddToViewport();
        }
        if(auto instance = CreateWidget<UDialogueRowWidgetManager>(PC, dialogueRowWidgetManagerClass))
        {
            dialogueRowWidgetManager = instance;
            dialogueRowWidgetManager->SetVisibility(ESlateVisibility::Visible);
            dialogueRowWidgetManager->AddToViewport();
        }
        if(auto instance = CreateWidget<UInventoryWidget>(PC, inventoryWidgetClass))
        {
            inventoryWidget = instance;
            inventoryWidget->SetVisibility(ESlateVisibility::Hidden);

            if(auto player = Cast<APlayerBase>(PC->GetPawn()))
            {
                if(player->leftPocketItem)
                    inventoryWidget->firstItemDescriptionText->SetText(player->leftPocketItem->GetComponentByClass<UInventoryInteractableModificator>()->name);
                else
                    inventoryWidget->firstItemDescriptionText->SetText(FText::GetEmpty());
                if(player->rightPocketItem)
                    inventoryWidget->secondItemDescriptionText->SetText(player->rightPocketItem->GetComponentByClass<UInventoryInteractableModificator>()->name);
                else
                    inventoryWidget->secondItemDescriptionText->SetText(FText::GetEmpty());
            }

            inventoryWidget->AddToViewport();
        }
        if(auto instance = CreateWidget<UJournalWidget>(PC, journalWidgetClass))
        {
            journalWidget = instance;
            journalWidget->SetVisibility(ESlateVisibility::Hidden);
            journalWidget->AddToViewport();
        }
    }
}

void UWidgetsManager::UpdateInputKeys()
{
    // PLAYER CANT CHANGE UI KEYS FROM SETTINGS (maybe somewhere in future project)

    //cutsceneSkipWidget->keyText->SetText(keyText);

}

void UWidgetsManager::HideWidgets()
{
    for(auto& widget : overlayWidgetsInstances)
        widget->SetVisibility(ESlateVisibility::Hidden);

    if(interactableHintWidgetManager)
        interactableHintWidgetManager->Remove(nullptr);
    if(inventoryWidget)
        inventoryWidget->SetVisibility(ESlateVisibility::Hidden);
    if(journalWidget)
        journalWidget->SetVisibility(ESlateVisibility::Hidden);
}

void UWidgetsManager::ShowWidgets()
{
    for(auto& widget : overlayWidgetsInstances)
        widget->SetVisibility(ESlateVisibility::Visible);

    if(interactableHintWidgetManager)
        interactableHintWidgetManager->Append(nullptr);
}

void UWidgetsManager::UpdateWidgetsOwner()
{
    if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0))
    {
        for(auto& widget : permaOverlayWidgetsInstances)
            widget->SetOwningPlayer(PC);
        for(auto& widget : overlayWidgetsInstances)
            widget->SetOwningPlayer(PC);
    }
}



void UWidgetsManager::ShowMainMenu(bool pause)
{
    mainMenuWidget->Show(pause);
}

void UWidgetsManager::HideMainMenu()
{
    mainMenuWidget->Hide();
}



void UWidgetsManager::ShowInteractionHints(const UInteractableModificator* modificator)
{
    if(interactableHintWidgetManager)
        interactableHintWidgetManager->Append(modificator);
}
void UWidgetsManager::HideInteractionHints(const UInteractableModificator* modificator)
{
    if(interactableHintWidgetManager)
        interactableHintWidgetManager->Remove(modificator);
}
void UWidgetsManager::AnimateInteractionHint(const UInteractableModificator* modificator, const int32 index, const EInputAnimatedWidgetAnimation animation)
{
    if(interactableHintWidgetManager)
        interactableHintWidgetManager->AnimateInteractionHint(modificator, index, animation);
}



void UWidgetsManager::EnableCutsceneWidget(FSkipCutsceneDelegate& skipCutsceneDelegate)
{
    cutsceneSkipWidget->skipCutsceneDelegate = skipCutsceneDelegate;
    cutsceneSkipWidget->SetVisibility(ESlateVisibility::Visible);
}
void UWidgetsManager::DisableCutsceneWidget()
{
    cutsceneSkipWidget->SetVisibility(ESlateVisibility::Hidden);
}
void UWidgetsManager::AnimateCutsceneWidget(const EInputAnimatedWidgetAnimation animation)
{
    cutsceneSkipWidget->RunAnimation(animation);
}



void UWidgetsManager::ShowQuickTimeEvent(const int32 id, const struct FQuickTimeEventEnqueProperties& properties)
{
    quickTimeEventWidgetManager->ShowEvent(id, properties);
}

EQuickTimeEventResult UWidgetsManager::RemoveQuickTimeEvent(const int32 id)
{
    return quickTimeEventWidgetManager->RemoveEvent(id);
}

EQuickTimeEventResult UWidgetsManager::ProcessQuickTimeEvent(const int32 id, const bool released)
{
    return quickTimeEventWidgetManager->AnimateEvent(id, released);
}



void UWidgetsManager::SetInputDialogueWidget(const FKey key, const FText desc, FDialogueSkipDelegate& delegate)
{
    dialogueRowWidgetManager->SetInput(key, desc, delegate);
}

void UWidgetsManager::ShowDialogueWidget(const FDialogueRow& dialogue)
{
    dialogueRowWidgetManager->Append(dialogue);
}
void UWidgetsManager::HideDialogueWidget(const FDialogueRow& dialogue)
{
    dialogueRowWidgetManager->Remove(dialogue);
}
void UWidgetsManager::AnimateDialogueWidget(const EInputAnimatedWidgetAnimation animation)
{
    dialogueRowWidgetManager->AnimateSkipWidget(animation);
}



void UWidgetsManager::ShowInventory()
{
    inventoryWidget->Show();
}
void UWidgetsManager::ShowInventory(FText key1, FText key2)
{
    inventoryWidget->firstItemKeyText->SetText(key2);
    inventoryWidget->secondItemKeyText->SetText(key1);
    ShowInventory();
}
void UWidgetsManager::SetInventoryFirstItem(FText item)
{
    inventoryWidget->firstItemDescriptionText->SetText(item);
}
void UWidgetsManager::SetInventorySecondItem(FText item)
{
    inventoryWidget->secondItemDescriptionText->SetText(item);
}

void UWidgetsManager::ShowJournal()
{
    journalWidget->Show();
}

void UWidgetsManager::UpdateJournal(TArray<FText> text)
{
    journalWidget->Update(text);
    ShowJournal();
}
