// Oleg Petruny proprietary.


#include "MainGameModeBase.h"

#include "Engine/World.h"
#include "GameFramework/SpectatorPawn.h"
#include "Kismet/GameplayStatics.h"
#include "UObject/ScriptInterface.h"

#include "CustomGameInstance.h"
#include "CutsceneManager.h"
#include "DialogueManager.h"
#include "Levels/LevelBase.h"
#include "QuestManager.h"
#include "QuickTimeEvent.h"
#include "Widgets/WidgetsManager.h"

AMainGameModeBase* AMainGameModeBase::_instance = nullptr;
TStrongObjectPtr<UWidgetsManager> AMainGameModeBase::_widgetsManager = nullptr;
TStrongObjectPtr<UCutsceneManager> AMainGameModeBase::_cutsceneManager = nullptr;
TStrongObjectPtr<UQuickTimeEventManager> AMainGameModeBase::_quickTimeEventManager = nullptr;
TStrongObjectPtr<UDialogueManager> AMainGameModeBase::_dialogueManager = nullptr;
TStrongObjectPtr<ALevelBase> AMainGameModeBase::leadLevel = nullptr;

void AMainGameModeBase::StartPlay()
{
    _instance = this;
    _widgetsManager = TStrongObjectPtr<UWidgetsManager>{ NewObject<UWidgetsManager>(this, widgetManagerClass) };
    _cutsceneManager = TStrongObjectPtr<UCutsceneManager>{ NewObject<UCutsceneManager>(this) };
    _quickTimeEventManager = TStrongObjectPtr<UQuickTimeEventManager>{ NewObject<UQuickTimeEventManager>(this) };
    _dialogueManager = TStrongObjectPtr<UDialogueManager>{ NewObject<UDialogueManager>(this) };

    AGameModeBase::StartPlay();

    _widgetsManager->Init();
}

void AMainGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
    _cutsceneManager->LockCallback(true);
    //_cutsceneManager->ClearQueue();
}

bool AMainGameModeBase::SetPause(APlayerController* PC, FCanUnpause CanUnpauseDelegate)
{
    if(_widgetsManager)
    {
        if(IsPaused())
        {
            _widgetsManager->HideWidgets();
        }
        else
        {
            _widgetsManager->ShowWidgets();
        }
    }

    return AGameModeBase::SetPause(PC, CanUnpauseDelegate);
}

UWidgetsManager* AMainGameModeBase::GetWidgetsManager()
{
    return _widgetsManager.Get();
}
UCutsceneManager* AMainGameModeBase::GetCutsceneManager()
{
    return _cutsceneManager.Get();
}

UQuickTimeEventManager* AMainGameModeBase::GetQuickTimeEventManager()
{
    return _quickTimeEventManager.Get();
}

UDialogueManager* AMainGameModeBase::GetDialogueManager()
{
    return _dialogueManager.Get();
}

void AMainGameModeBase::CallNextLevelState()
{
    if(leadLevel)
        leadLevel->CallNextState();
}

void AMainGameModeBase::CallLevelEvent(int32 id)
{
    if(leadLevel)
        leadLevel->CallEvent(id);
}

void AMainGameModeBase::UpdateQuests(TArray<FText> items)
{
    if(_instance && _instance->questsUpdateDelegate.IsBound())
        _instance->questsUpdateDelegate.Broadcast(items);
}

void AMainGameModeBase::SwitchCameraMode()
{
    static TWeakObjectPtr<APawn> _playerPawn = nullptr;

    if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0))
    {
        if(auto pawn = PC->GetPawn())
        {
            if(!_playerPawn.IsValid())
            {
                auto spawnLoc = pawn->GetActorLocation();
                auto spawnRot = pawn->GetActorRotation();
                if(auto cameraPawn = GetWorld()->SpawnActor<APawn>(SpectatorClass, spawnLoc, spawnRot))
                {
                    _playerPawn = pawn;
                    PC->Possess(cameraPawn);
                }
            }
            else
            {
                PC->Possess(_playerPawn.Get());
                pawn->Destroy();
                _playerPawn = nullptr;
            }
        }
    }

    if(_widgetsManager)
    {
        _widgetsManager->UpdateWidgetsOwner();
    }
}
