// Project Lab - NHTV Igad

#include "UnrealProject.h"
#include "ScreenOverlay.h"
#include "OverlayMessageBox.h"
#include "OverlayProgressBar.h"

UScreenOverlay::UScreenOverlay(const FObjectInitializer& init)
	: Super(init)
{
}
void UScreenOverlay::NativeConstruct()
{
	Super::NativeConstruct();
	m_msgBox = Cast<UOverlayMessageBox>(WidgetTree->FindWidget("MessageBox"));
	m_progressBar = Cast<UOverlayProgressBar>(WidgetTree->FindWidget("ProgressBar"));
	m_background = Cast<UBorder>(WidgetTree->FindWidget("Background"));
	check(m_msgBox);
	check(m_progressBar);
	check(m_background);
	UpdateOverlays();
	UpdateMsgBoxes();
	UpdateVisiblity();
	m_msgBox->onClosed.AddDynamic(this, &UScreenOverlay::OnMessageBoxClosed);
}
void UScreenOverlay::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
	Super::NativeTick(MyGeometry, InDeltaTime);

	// Check all active screen overlays, remove the inactive ones
	for(int32 i = 0; i < m_overlayItems.Num();)
	{
		if(m_overlayItems[i]->m_remove)
		{
			m_overlayItems.RemoveAt(i);
			UpdateOverlays();
			UpdateVisiblity();
		}
		else
		{
			i++;
		}
	}

	// Check the currently shown message box, remove it if inactive
	UMsgBoxInfo* msgBox = GetMessageBoxItem();
	if(msgBox && msgBox->m_remove)
	{
		if(msgBox->onClosed.IsBound())
		{
			msgBox->onClosed.Execute(msgBox->m_closeResult);
		}
		m_messageBoxItems.Remove(msgBox);
		UpdateMsgBoxes();
		UpdateVisiblity();

		// Show remaining message boxes
		if(m_messageBoxItems.Num() > 0)
		{
			OpenSubMenu(m_msgBox);
		}
	}
}

UOverlayInfo* UScreenOverlay::ShowOverlay(FString message)
{
	// Add a new overlay item to the list
	UOverlayInfo* info = NewObject<UOverlayInfo>();
	info->message = message;
	m_overlayItems.Add(info);

	// Update Widget blueprint
	UpdateOverlays();
	UpdateVisiblity();
	return info;
}

UMsgBoxInfo* UScreenOverlay::ShowMessageBox(FString caption, FString message, TArray<FString> options, FString def /*= FString()*/)
{
	// Add a new message box at the end of the queue
	UMsgBoxInfo* info = NewObject<UMsgBoxInfo>();
	info->message = message;
	info->caption = caption;
	info->options = options;
	info->defaultOption = def;
	m_messageBoxItems.Add(info);

	// Update Widget blueprint
	UpdateMsgBoxes();
	UpdateVisiblity();

	OpenSubMenu(m_msgBox);

	return info;
}
UMsgBoxInfo* UScreenOverlay::ShowMessageBoxCallback(FOverlayItemClosed cb, FString caption, FString message, TArray<FString> options, FString def /*= ""*/)
{
	// Add a new message box at the end of the queue
	UMsgBoxInfo* info = NewObject<UMsgBoxInfo>();
	info->message = message;
	info->caption = caption;
	info->options = options;
	info->onClosed = cb;
	info->defaultOption = def;
	m_messageBoxItems.Add(info);

	// Update Widget blueprint
	UpdateMsgBoxes();
	UpdateVisiblity();

	OpenSubMenu(m_msgBox);

	return info;
}

void UScreenOverlay::OnMessageBoxClosed()
{
	m_messageBoxItems.Last()->Close(m_msgBox->returnCode);
}

TArray<UOverlayInfo*>& UScreenOverlay::GetOverlayItems()
{
	return m_overlayItems;
}

UMsgBoxInfo* UScreenOverlay::GetMessageBoxItem()
{
	if(m_messageBoxItems.Num() == 0)
	{
		return nullptr;
	}
	return m_messageBoxItems[0];
}
void UScreenOverlay::UpdateOverlays()
{
	if(m_overlayItems.Num() != 0)
	{
		m_progressBar->SetVisibility(ESlateVisibility::Visible);
		m_progressBar->SetOverlayInfo(m_overlayItems.Last());
	}
	else
	{
		m_progressBar->SetVisibility(ESlateVisibility::Hidden);
	}
}
void UScreenOverlay::UpdateMsgBoxes()
{
	if(m_messageBoxItems.Num() != 0)
	{
		m_msgBox->SetMessageBoxInfo(GetMessageBoxItem());
		m_msgBox->SetVisibility(ESlateVisibility::Visible);
	}
	else
	{
		m_msgBox->SetVisibility(ESlateVisibility::Hidden);
	}
}
void UScreenOverlay::UpdateVisiblity()
{
	if(m_messageBoxItems.Num() != 0 || m_overlayItems.Num() != 0)
	{
		m_background->SetVisibility(ESlateVisibility::Visible);
		blockInput = true;
	}
	else
	{
		m_background->SetVisibility(ESlateVisibility::Hidden);
		blockInput = false;
	}
}

UOverlayQueueItem::UOverlayQueueItem(const FObjectInitializer& init)
	: Super(init)
{
	m_remove = false;
}
void UOverlayQueueItem::Close(int32 result)
{
	m_remove = true;
	m_closeResult = result;
}

UMsgBoxInfo::UMsgBoxInfo(const FObjectInitializer& init)
	: Super(init)
{
	message = "nothing";
	options.Add("OK");
}

UOverlayInfo::UOverlayInfo(const FObjectInitializer& init)
	: Super(init)
{
	blockInput = true;
	message = "nothing";
}