#include "HyperTwistUX/HyperTwistPauseMenuWidget.h"

#include "Blueprint/WidgetTree.h"
#include "Components/Border.h"
#include "Components/Button.h"
#include "Components/ButtonSlot.h"
#include "Components/HorizontalBox.h"
#include "Components/HorizontalBoxSlot.h"
#include "Components/Overlay.h"
#include "Components/OverlaySlot.h"
#include "Components/SizeBox.h"
#include "Components/Spacer.h"
#include "Components/TextBlock.h"
#include "Components/VerticalBox.h"
#include "Components/VerticalBoxSlot.h"
#include "Components/WidgetSwitcher.h"
#include "HyperTwistUX/HyperTwistSettingsPanelWidget.h"
#include "Input/Reply.h"
#include "InputCoreTypes.h"

namespace HyperTwistPauseMenuWidgetInternal
{
	const FLinearColor BackdropColor(0.004f, 0.009f, 0.018f, 0.88f);
	const FLinearColor PanelColor(0.018f, 0.030f, 0.049f, 0.99f);
	const FLinearColor CardColor(0.045f, 0.075f, 0.108f, 1.0f);
	const FLinearColor AccentColor(0.10f, 0.92f, 0.80f, 1.0f);
	const FLinearColor WarmColor(1.0f, 0.61f, 0.22f, 1.0f);
	const FLinearColor PrimaryText(0.94f, 0.98f, 1.0f, 1.0f);
	const FLinearColor MutedText(0.62f, 0.72f, 0.80f, 1.0f);

	UTextBlock* AddText(
		UWidgetTree* WidgetTree,
		UVerticalBox* Parent,
		const FString& Text,
		const int32 Size,
		const FLinearColor& Color,
		const FName& Name = NAME_None
	)
	{
		UTextBlock* Block = WidgetTree->ConstructWidget<UTextBlock>(
			UTextBlock::StaticClass(),
			Name);
		Block->SetText(FText::FromString(Text));
		Block->SetAutoWrapText(true);
		Block->SetColorAndOpacity(FSlateColor(Color));
		FSlateFontInfo Font = Block->GetFont();
		Font.Size = Size;
		Block->SetFont(Font);
		if (UVerticalBoxSlot* Slot = Parent->AddChildToVerticalBox(Block))
		{
			Slot->SetPadding(FMargin(0.0f, 3.0f));
		}
		return Block;
	}

	UButton* AddButton(
		UWidgetTree* WidgetTree,
		UVerticalBox* Parent,
		const FString& Label,
		const FName& Name,
		const bool bPrimary = false,
		const bool bDanger = false
	)
	{
		UButton* Button = WidgetTree->ConstructWidget<UButton>(
			UButton::StaticClass(),
			Name);
		Button->SetBackgroundColor(
			bPrimary
				? AccentColor
				: bDanger
					? FLinearColor(0.30f, 0.065f, 0.070f, 1.0f)
					: CardColor);
		UTextBlock* Text = WidgetTree->ConstructWidget<UTextBlock>(
			UTextBlock::StaticClass());
		Text->SetText(FText::FromString(Label));
		Text->SetJustification(ETextJustify::Center);
		Text->SetColorAndOpacity(FSlateColor(
			bPrimary ? FLinearColor(0.01f, 0.04f, 0.05f, 1.0f) : PrimaryText));
		FSlateFontInfo Font = Text->GetFont();
		Font.Size = 16;
		Text->SetFont(Font);
		Button->AddChild(Text);
		if (UButtonSlot* ButtonSlot = Cast<UButtonSlot>(Text->Slot))
		{
			ButtonSlot->SetPadding(FMargin(22.0f, 12.0f));
			ButtonSlot->SetHorizontalAlignment(HAlign_Center);
		}
		if (UVerticalBoxSlot* Slot = Parent->AddChildToVerticalBox(Button))
		{
			Slot->SetPadding(FMargin(0.0f, 5.0f));
			Slot->SetHorizontalAlignment(HAlign_Fill);
		}
		return Button;
	}
}

UHyperTwistPauseMenuWidget::UHyperTwistPauseMenuWidget(
	const FObjectInitializer& ObjectInitializer
)
	: Super(ObjectInitializer)
{
	SetIsFocusable(true);
}

TSharedRef<SWidget> UHyperTwistPauseMenuWidget::RebuildWidget()
{
	Initialize();
	EnsureWidgetTreeBuilt();
	return Super::RebuildWidget();
}

FReply UHyperTwistPauseMenuWidget::NativeOnKeyDown(
	const FGeometry& InGeometry,
	const FKeyEvent& InKeyEvent
)
{
	static_cast<void>(InGeometry);
	if (InKeyEvent.GetKey() == EKeys::Escape)
	{
		if (PageSwitcher != nullptr && PageSwitcher->GetActiveWidgetIndex() != 0)
		{
			PageSwitcher->SetActiveWidgetIndex(0);
		}
		else
		{
			OnResumeRequested.Broadcast();
		}
		return FReply::Handled();
	}
	return Super::NativeOnKeyDown(InGeometry, InKeyEvent);
}

bool UHyperTwistPauseMenuWidget::PreparePauseSurface()
{
	EnsureWidgetTreeBuilt();
	SetPuzzleContext(PuzzleTitle, PuzzleSubtitle);
	return IsPauseSurfaceReady();
}

bool UHyperTwistPauseMenuWidget::IsPauseSurfaceReady() const
{
	return WidgetTree != nullptr
		&& WidgetTree->RootWidget != nullptr
		&& PageSwitcher != nullptr
		&& PageSwitcher->GetNumWidgets() == 2
		&& SettingsPanel != nullptr
		&& SettingsPanel->IsSettingsSurfaceReady();
}

void UHyperTwistPauseMenuWidget::SetPuzzleContext(
	const FString& Title,
	const FString& Subtitle
)
{
	PuzzleTitle = Title.IsEmpty() ? TEXT("HyperTwist") : Title;
	PuzzleSubtitle = Subtitle.IsEmpty() ? TEXT("Puzzle paused") : Subtitle;
	if (PuzzleTitleText != nullptr)
	{
		PuzzleTitleText->SetText(FText::FromString(PuzzleTitle));
	}
	if (PuzzleSubtitleText != nullptr)
	{
		PuzzleSubtitleText->SetText(FText::FromString(PuzzleSubtitle));
	}
}

void UHyperTwistPauseMenuWidget::EnsureWidgetTreeBuilt()
{
	using namespace HyperTwistPauseMenuWidgetInternal;
	if (WidgetTree == nullptr || WidgetTree->RootWidget != nullptr)
	{
		return;
	}

	UOverlay* Root = WidgetTree->ConstructWidget<UOverlay>(
		UOverlay::StaticClass(),
		TEXT("HyperTwistPauseRoot"));
	WidgetTree->RootWidget = Root;

	UBorder* Backdrop = WidgetTree->ConstructWidget<UBorder>(
		UBorder::StaticClass(),
		TEXT("HyperTwistPauseBackdrop"));
	Backdrop->SetBrushColor(BackdropColor);
	Root->AddChildToOverlay(Backdrop);

	PageSwitcher = WidgetTree->ConstructWidget<UWidgetSwitcher>(
		UWidgetSwitcher::StaticClass(),
		TEXT("HyperTwistPausePageSwitcher"));
	if (UOverlaySlot* SwitcherSlot = Root->AddChildToOverlay(PageSwitcher))
	{
		SwitcherSlot->SetHorizontalAlignment(HAlign_Fill);
		SwitcherSlot->SetVerticalAlignment(VAlign_Fill);
		SwitcherSlot->SetPadding(FMargin(34.0f));
	}

	UHorizontalBox* PausePage = WidgetTree->ConstructWidget<UHorizontalBox>(
		UHorizontalBox::StaticClass(),
		TEXT("HyperTwistPauseMainPage"));
	PageSwitcher->AddChild(PausePage);

	USpacer* LeftSpacer = WidgetTree->ConstructWidget<USpacer>(
		USpacer::StaticClass());
	if (UHorizontalBoxSlot* SpacerSlot = PausePage->AddChildToHorizontalBox(LeftSpacer))
	{
		SpacerSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill));
	}

	USizeBox* PanelSize = WidgetTree->ConstructWidget<USizeBox>(
		USizeBox::StaticClass(),
		TEXT("HyperTwistPausePanelSize"));
	PanelSize->SetWidthOverride(560.0f);
	if (UHorizontalBoxSlot* PanelSlot = PausePage->AddChildToHorizontalBox(PanelSize))
	{
		PanelSlot->SetVerticalAlignment(VAlign_Center);
	}
	UBorder* Panel = WidgetTree->ConstructWidget<UBorder>(
		UBorder::StaticClass(),
		TEXT("HyperTwistPausePanel"));
	Panel->SetPadding(FMargin(34.0f));
	Panel->SetBrushColor(PanelColor);
	PanelSize->AddChild(Panel);
	UVerticalBox* Content = WidgetTree->ConstructWidget<UVerticalBox>(
		UVerticalBox::StaticClass(),
		TEXT("HyperTwistPauseContent"));
	Panel->AddChild(Content);

	AddText(WidgetTree, Content, TEXT("PAUSED"), 13, AccentColor);
	PuzzleTitleText = AddText(
		WidgetTree,
		Content,
		PuzzleTitle,
		32,
		PrimaryText,
		TEXT("HyperTwistPausePuzzleTitle"));
	PuzzleSubtitleText = AddText(
		WidgetTree,
		Content,
		PuzzleSubtitle,
		14,
		MutedText,
		TEXT("HyperTwistPausePuzzleSubtitle"));
	AddText(
		WidgetTree,
		Content,
		TEXT("Your state remains exactly where you left it."),
		13,
		MutedText);

	USpacer* MenuSpacer = WidgetTree->ConstructWidget<USpacer>(
		USpacer::StaticClass());
	MenuSpacer->SetSize(FVector2D(1.0f, 20.0f));
	Content->AddChildToVerticalBox(MenuSpacer);

	UButton* ResumeButton = AddButton(
		WidgetTree,
		Content,
		TEXT("Resume"),
		TEXT("HyperTwistPauseResumeButton"),
		true);
	UButton* SettingsButton = AddButton(
		WidgetTree,
		Content,
		TEXT("Settings & Controls"),
		TEXT("HyperTwistPauseSettingsButton"));
	UButton* MainMenuButton = AddButton(
		WidgetTree,
		Content,
		TEXT("Return to Puzzle Library"),
		TEXT("HyperTwistPauseMainMenuButton"));
	UButton* QuitButton = AddButton(
		WidgetTree,
		Content,
		TEXT("Exit HyperTwist"),
		TEXT("HyperTwistPauseQuitButton"),
		false,
		true);
	ResumeButton->OnClicked.AddDynamic(this, &UHyperTwistPauseMenuWidget::HandleResumeClicked);
	SettingsButton->OnClicked.AddDynamic(this, &UHyperTwistPauseMenuWidget::HandleSettingsClicked);
	MainMenuButton->OnClicked.AddDynamic(this, &UHyperTwistPauseMenuWidget::HandleMainMenuClicked);
	QuitButton->OnClicked.AddDynamic(this, &UHyperTwistPauseMenuWidget::HandleQuitClicked);

	AddText(
		WidgetTree,
		Content,
		TEXT("Esc resume  |  F10 puzzle library"),
		12,
		WarmColor);

	USpacer* RightSpacer = WidgetTree->ConstructWidget<USpacer>(
		USpacer::StaticClass());
	if (UHorizontalBoxSlot* SpacerSlot = PausePage->AddChildToHorizontalBox(RightSpacer))
	{
		SpacerSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill));
	}

	SettingsPanel = WidgetTree->ConstructWidget<UHyperTwistSettingsPanelWidget>(
		UHyperTwistSettingsPanelWidget::StaticClass(),
		TEXT("HyperTwistPauseSettingsPanel"));
	SettingsPanel->bShowCloseButton = true;
	SettingsPanel->OnCloseRequested.AddDynamic(
		this,
		&UHyperTwistPauseMenuWidget::HandleSettingsClosed);
	SettingsPanel->PrepareSettingsSurface();
	PageSwitcher->AddChild(SettingsPanel);
	PageSwitcher->SetActiveWidgetIndex(0);
}

void UHyperTwistPauseMenuWidget::HandleResumeClicked()
{
	OnResumeRequested.Broadcast();
}

void UHyperTwistPauseMenuWidget::HandleSettingsClicked()
{
	if (SettingsPanel != nullptr)
	{
		SettingsPanel->ReloadPreferences();
	}
	PageSwitcher->SetActiveWidgetIndex(1);
}

void UHyperTwistPauseMenuWidget::HandleSettingsClosed()
{
	PageSwitcher->SetActiveWidgetIndex(0);
	SetKeyboardFocus();
}

void UHyperTwistPauseMenuWidget::HandleMainMenuClicked()
{
	OnMainMenuRequested.Broadcast();
}

void UHyperTwistPauseMenuWidget::HandleQuitClicked()
{
	OnQuitRequested.Broadcast();
}
