// Copyright Pacificao. All Rights Reserved.

#include "AgrarianMvpFrontendWidget.h"

#include "InputCoreTypes.h"
#include "Rendering/DrawElements.h"
#include "Styling/CoreStyle.h"

void UAgrarianMvpFrontendWidget::NativeConstruct()
{
	Super::NativeConstruct();
	bIsFocusable = true;
	SetKeyboardFocus();
}

FReply UAgrarianMvpFrontendWidget::NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
{
	if (ActiveScreen == EAgrarianMvpFrontendScreen::CharacterSelection)
	{
		const FKey Key = InKeyEvent.GetKey();
		if (Key == EKeys::Left || Key == EKeys::A)
		{
			SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype::YoungAdultMale);
			return FReply::Handled();
		}

		if (Key == EKeys::Right || Key == EKeys::D)
		{
			SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype::YoungAdultFemale);
			return FReply::Handled();
		}

		if (Key == EKeys::Enter || Key == EKeys::SpaceBar)
		{
			SetActiveScreen(EAgrarianMvpFrontendScreen::JoinServer);
			return FReply::Handled();
		}
	}
	else if (ActiveScreen == EAgrarianMvpFrontendScreen::JoinServer)
	{
		const FKey Key = InKeyEvent.GetKey();
		if (Key == EKeys::Enter || Key == EKeys::SpaceBar)
		{
			SetActiveScreen(EAgrarianMvpFrontendScreen::Loading);
			return FReply::Handled();
		}

		if (Key == EKeys::BackSpace || Key == EKeys::Escape)
		{
			SetActiveScreen(EAgrarianMvpFrontendScreen::CharacterSelection);
			return FReply::Handled();
		}
	}

	return Super::NativeOnKeyDown(InGeometry, InKeyEvent);
}

void UAgrarianMvpFrontendWidget::SetActiveScreen(EAgrarianMvpFrontendScreen NewScreen)
{
	ActiveScreen = NewScreen;
	InvalidateLayoutAndVolatility();
}

void UAgrarianMvpFrontendWidget::SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype NewArchetype)
{
	SelectedCharacterArchetype = NewArchetype;
	InvalidateLayoutAndVolatility();
}

int32 UAgrarianMvpFrontendWidget::NativePaint(
	const FPaintArgs& Args,
	const FGeometry& AllottedGeometry,
	const FSlateRect& MyCullingRect,
	FSlateWindowElementList& OutDrawElements,
	int32 LayerId,
	const FWidgetStyle& InWidgetStyle,
	bool bParentEnabled) const
{
	LayerId = Super::NativePaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);

	const FVector2D Size = AllottedGeometry.GetLocalSize();
	const float Scale = FMath::Clamp(UiScale, 0.75f, 1.5f);

	FSlateDrawElement::MakeBox(
		OutDrawElements,
		++LayerId,
		AllottedGeometry.ToPaintGeometry(FVector2f(Size), FSlateLayoutTransform(FVector2f::ZeroVector)),
		FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
		ESlateDrawEffect::None,
		FLinearColor(0.015f, 0.018f, 0.014f, 0.92f));

	const FVector2D PanelSize(
		FMath::Min(Size.X - 48.0f, 780.0f * Scale),
		FMath::Min(Size.Y - 48.0f, 430.0f * Scale));
	const FVector2D PanelPosition(
		(Size.X - PanelSize.X) * 0.5f,
		(Size.Y - PanelSize.Y) * 0.5f);

	FSlateDrawElement::MakeBox(
		OutDrawElements,
		++LayerId,
		AllottedGeometry.ToPaintGeometry(FVector2f(PanelSize), FSlateLayoutTransform(FVector2f(PanelPosition))),
		FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
		ESlateDrawEffect::None,
		FLinearColor(0.035f, 0.045f, 0.034f, 0.96f));

	FSlateDrawElement::MakeBox(
		OutDrawElements,
		++LayerId,
		AllottedGeometry.ToPaintGeometry(FVector2f(PanelSize.X, 4.0f * Scale), FSlateLayoutTransform(FVector2f(PanelPosition))),
		FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
		ESlateDrawEffect::None,
		FLinearColor(0.45f, 0.72f, 0.40f, 1.0f));

	if (ActiveScreen == EAgrarianMvpFrontendScreen::MainMenu)
	{
		DrawMainMenu(OutDrawElements, LayerId, AllottedGeometry, PanelPosition, PanelSize, Scale);
	}
	else if (ActiveScreen == EAgrarianMvpFrontendScreen::CharacterSelection)
	{
		DrawCharacterSelection(OutDrawElements, LayerId, AllottedGeometry, PanelPosition, PanelSize, Scale);
	}
	else if (ActiveScreen == EAgrarianMvpFrontendScreen::JoinServer)
	{
		DrawJoinServer(OutDrawElements, LayerId, AllottedGeometry, PanelPosition, PanelSize, Scale);
	}
	else if (ActiveScreen == EAgrarianMvpFrontendScreen::Loading)
	{
		DrawLoading(OutDrawElements, LayerId, AllottedGeometry, PanelPosition, PanelSize, Scale);
	}

	return LayerId;
}

void UAgrarianMvpFrontendWidget::DrawMainMenu(
	FSlateWindowElementList& OutDrawElements,
	int32& LayerId,
	const FGeometry& AllottedGeometry,
	const FVector2D& PanelPosition,
	const FVector2D& PanelSize,
	float Scale) const
{
	const float ContentX = PanelPosition.X + (48.0f * Scale);
	const float ContentWidth = PanelSize.X - (96.0f * Scale);
	const FSlateFontInfo TitleFont = FCoreStyle::GetDefaultFontStyle("Bold", FMath::RoundToInt(54.0f * Scale));
	const FSlateFontInfo SubtitleFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(22.0f * Scale));
	const FSlateFontInfo ButtonFont = FCoreStyle::GetDefaultFontStyle("Bold", FMath::RoundToInt(24.0f * Scale));
	const FSlateFontInfo HintFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(16.0f * Scale));

	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, MainMenuTitle, FVector2D(ContentX, PanelPosition.Y + (58.0f * Scale)), ContentWidth, TitleFont, FLinearColor(0.92f, 0.98f, 0.84f, 1.0f));
	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, MainMenuSubtitle, FVector2D(ContentX + (4.0f * Scale), PanelPosition.Y + (128.0f * Scale)), ContentWidth, SubtitleFont, FLinearColor(0.72f, 0.80f, 0.68f, 1.0f));

	const FVector2D ButtonPosition(ContentX, PanelPosition.Y + (230.0f * Scale));
	const FVector2D ButtonSize(FMath::Min(ContentWidth, 280.0f * Scale), 58.0f * Scale);
	FSlateDrawElement::MakeBox(
		OutDrawElements,
		++LayerId,
		AllottedGeometry.ToPaintGeometry(FVector2f(ButtonSize), FSlateLayoutTransform(FVector2f(ButtonPosition))),
		FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
		ESlateDrawEffect::None,
		FLinearColor(0.35f, 0.58f, 0.30f, 0.95f));

	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, PrimaryActionLabel, ButtonPosition + FVector2D(22.0f * Scale, 12.0f * Scale), ButtonSize.X - (44.0f * Scale), ButtonFont, FLinearColor(0.96f, 1.0f, 0.90f, 1.0f));
	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Placeholder flow: splash, startup credits, character selection, join, loading, then Ground Zero.")), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (66.0f * Scale)), ContentWidth, HintFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
}

void UAgrarianMvpFrontendWidget::DrawCharacterSelection(
	FSlateWindowElementList& OutDrawElements,
	int32& LayerId,
	const FGeometry& AllottedGeometry,
	const FVector2D& PanelPosition,
	const FVector2D& PanelSize,
	float Scale) const
{
	const float ContentX = PanelPosition.X + (44.0f * Scale);
	const float ContentWidth = PanelSize.X - (88.0f * Scale);
	const FSlateFontInfo TitleFont = FCoreStyle::GetDefaultFontStyle("Bold", FMath::RoundToInt(34.0f * Scale));
	const FSlateFontInfo BodyFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(18.0f * Scale));
	const FSlateFontInfo CardTitleFont = FCoreStyle::GetDefaultFontStyle("Bold", FMath::RoundToInt(22.0f * Scale));
	const FSlateFontInfo LabelFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(15.0f * Scale));

	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Choose your first settler")), FVector2D(ContentX, PanelPosition.Y + (34.0f * Scale)), ContentWidth, TitleFont, FLinearColor(0.92f, 0.98f, 0.84f, 1.0f));
	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("MVP placeholder landing page before entering Ground Zero.")), FVector2D(ContentX + (2.0f * Scale), PanelPosition.Y + (82.0f * Scale)), ContentWidth, BodyFont, FLinearColor(0.72f, 0.80f, 0.68f, 1.0f));

	const FVector2D CardSize((ContentWidth - (24.0f * Scale)) * 0.5f, 206.0f * Scale);
	const FVector2D MaleCardPosition(ContentX, PanelPosition.Y + (142.0f * Scale));
	const FVector2D FemaleCardPosition(ContentX + CardSize.X + (24.0f * Scale), MaleCardPosition.Y);

	auto DrawCharacterCard = [&](const FVector2D& CardPosition, const FText& Title, const FText& Summary, const FLinearColor& AccentColor, bool bSelected)
	{
		FSlateDrawElement::MakeBox(
			OutDrawElements,
			++LayerId,
			AllottedGeometry.ToPaintGeometry(FVector2f(CardSize), FSlateLayoutTransform(FVector2f(CardPosition))),
			FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
			ESlateDrawEffect::None,
			FLinearColor(0.055f, 0.065f, 0.05f, 0.95f));

		FSlateDrawElement::MakeBox(
			OutDrawElements,
			++LayerId,
			AllottedGeometry.ToPaintGeometry(FVector2f(CardSize.X, 3.0f * Scale), FSlateLayoutTransform(FVector2f(CardPosition))),
			FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
			ESlateDrawEffect::None,
			AccentColor);

		if (bSelected)
		{
			FSlateDrawElement::MakeBox(
				OutDrawElements,
				++LayerId,
				AllottedGeometry.ToPaintGeometry(FVector2f(CardSize.X, CardSize.Y), FSlateLayoutTransform(FVector2f(CardPosition))),
				FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
				ESlateDrawEffect::None,
				FLinearColor(AccentColor.R, AccentColor.G, AccentColor.B, 0.16f));
		}

		const FVector2D PortraitPosition = CardPosition + FVector2D(24.0f * Scale, 42.0f * Scale);
		const FVector2D PortraitSize(72.0f * Scale, 112.0f * Scale);
		FSlateDrawElement::MakeBox(
			OutDrawElements,
			++LayerId,
			AllottedGeometry.ToPaintGeometry(FVector2f(PortraitSize), FSlateLayoutTransform(FVector2f(PortraitPosition))),
			FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
			ESlateDrawEffect::None,
			FLinearColor(0.14f, 0.16f, 0.13f, 1.0f));

		DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, Title, CardPosition + FVector2D(116.0f * Scale, 42.0f * Scale), CardSize.X - (140.0f * Scale), CardTitleFont, FLinearColor(0.92f, 0.98f, 0.84f, 1.0f));
		DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, Summary, CardPosition + FVector2D(116.0f * Scale, 82.0f * Scale), CardSize.X - (140.0f * Scale), LabelFont, FLinearColor(0.72f, 0.78f, 0.68f, 1.0f));
		DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, bSelected ? FText::FromString(TEXT("Selected")) : FText::FromString(TEXT("Available")), CardPosition + FVector2D(116.0f * Scale, 144.0f * Scale), CardSize.X - (140.0f * Scale), LabelFont, bSelected ? AccentColor : FLinearColor(0.58f, 0.62f, 0.54f, 1.0f));
	};

	DrawCharacterCard(MaleCardPosition, FText::FromString(TEXT("Young adult male")), FText::FromString(TEXT("Average proportions, survival baseline, placeholder visual.")), FLinearColor(0.36f, 0.58f, 0.78f, 1.0f), SelectedCharacterArchetype == EAgrarianMvpCharacterArchetype::YoungAdultMale);
	DrawCharacterCard(FemaleCardPosition, FText::FromString(TEXT("Young adult female")), FText::FromString(TEXT("Average proportions, survival baseline, placeholder visual.")), FLinearColor(0.56f, 0.68f, 0.46f, 1.0f), SelectedCharacterArchetype == EAgrarianMvpCharacterArchetype::YoungAdultFemale);

	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::Format(FText::FromString(TEXT("Selected: {0}. Use Left/Right or A/D to choose; both choices enter the same MVP survival baseline.")), GetSelectedCharacterLabel()), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (46.0f * Scale)), ContentWidth, LabelFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
}

void UAgrarianMvpFrontendWidget::DrawJoinServer(
	FSlateWindowElementList& OutDrawElements,
	int32& LayerId,
	const FGeometry& AllottedGeometry,
	const FVector2D& PanelPosition,
	const FVector2D& PanelSize,
	float Scale) const
{
	const float ContentX = PanelPosition.X + (48.0f * Scale);
	const float ContentWidth = PanelSize.X - (96.0f * Scale);
	const FSlateFontInfo TitleFont = FCoreStyle::GetDefaultFontStyle("Bold", FMath::RoundToInt(34.0f * Scale));
	const FSlateFontInfo BodyFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(18.0f * Scale));
	const FSlateFontInfo AddressFont = FCoreStyle::GetDefaultFontStyle("Bold", FMath::RoundToInt(24.0f * Scale));
	const FSlateFontInfo HintFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(15.0f * Scale));

	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Join MVP server")), FVector2D(ContentX, PanelPosition.Y + (44.0f * Scale)), ContentWidth, TitleFont, FLinearColor(0.92f, 0.98f, 0.84f, 1.0f));
	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::Format(FText::FromString(TEXT("Character: {0}")), GetSelectedCharacterLabel()), FVector2D(ContentX + (2.0f * Scale), PanelPosition.Y + (94.0f * Scale)), ContentWidth, BodyFont, FLinearColor(0.72f, 0.80f, 0.68f, 1.0f));

	const FVector2D AddressPanelPosition(ContentX, PanelPosition.Y + (164.0f * Scale));
	const FVector2D AddressPanelSize(ContentWidth, 96.0f * Scale);
	FSlateDrawElement::MakeBox(
		OutDrawElements,
		++LayerId,
		AllottedGeometry.ToPaintGeometry(FVector2f(AddressPanelSize), FSlateLayoutTransform(FVector2f(AddressPanelPosition))),
		FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
		ESlateDrawEffect::None,
		FLinearColor(0.055f, 0.065f, 0.05f, 0.96f));

	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Server address")), AddressPanelPosition + FVector2D(24.0f * Scale, 14.0f * Scale), ContentWidth - (48.0f * Scale), HintFont, FLinearColor(0.58f, 0.64f, 0.54f, 1.0f));
	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, JoinServerAddress, AddressPanelPosition + FVector2D(24.0f * Scale, 42.0f * Scale), ContentWidth - (48.0f * Scale), AddressFont, FLinearColor(0.86f, 0.94f, 0.78f, 1.0f));

	const FVector2D ButtonPosition(ContentX, PanelPosition.Y + (300.0f * Scale));
	const FVector2D ButtonSize(FMath::Min(ContentWidth, 330.0f * Scale), 58.0f * Scale);
	FSlateDrawElement::MakeBox(
		OutDrawElements,
		++LayerId,
		AllottedGeometry.ToPaintGeometry(FVector2f(ButtonSize), FSlateLayoutTransform(FVector2f(ButtonPosition))),
		FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
		ESlateDrawEffect::None,
		FLinearColor(0.35f, 0.58f, 0.30f, 0.95f));

	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Continue to loading")), ButtonPosition + FVector2D(22.0f * Scale, 12.0f * Scale), ButtonSize.X - (44.0f * Scale), AddressFont, FLinearColor(0.96f, 1.0f, 0.90f, 1.0f));
	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Press Backspace or Escape to return to character selection.")), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (46.0f * Scale)), ContentWidth, HintFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
}

void UAgrarianMvpFrontendWidget::DrawLoading(
	FSlateWindowElementList& OutDrawElements,
	int32& LayerId,
	const FGeometry& AllottedGeometry,
	const FVector2D& PanelPosition,
	const FVector2D& PanelSize,
	float Scale) const
{
	const float ContentX = PanelPosition.X + (48.0f * Scale);
	const float ContentWidth = PanelSize.X - (96.0f * Scale);
	const FSlateFontInfo TitleFont = FCoreStyle::GetDefaultFontStyle("Bold", FMath::RoundToInt(34.0f * Scale));
	const FSlateFontInfo BodyFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(18.0f * Scale));
	const FSlateFontInfo HintFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(15.0f * Scale));

	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Preparing Ground Zero")), FVector2D(ContentX, PanelPosition.Y + (58.0f * Scale)), ContentWidth, TitleFont, FLinearColor(0.92f, 0.98f, 0.84f, 1.0f));
	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Loading terrain, weather, survival state, and server session data.")), FVector2D(ContentX + (2.0f * Scale), PanelPosition.Y + (108.0f * Scale)), ContentWidth, BodyFont, FLinearColor(0.72f, 0.80f, 0.68f, 1.0f));

	const FVector2D BarPosition(ContentX, PanelPosition.Y + (214.0f * Scale));
	const FVector2D BarSize(ContentWidth, 18.0f * Scale);
	FSlateDrawElement::MakeBox(
		OutDrawElements,
		++LayerId,
		AllottedGeometry.ToPaintGeometry(FVector2f(BarSize), FSlateLayoutTransform(FVector2f(BarPosition))),
		FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
		ESlateDrawEffect::None,
		FLinearColor(0.065f, 0.075f, 0.06f, 1.0f));

	FSlateDrawElement::MakeBox(
		OutDrawElements,
		++LayerId,
		AllottedGeometry.ToPaintGeometry(FVector2f(BarSize.X * 0.62f, BarSize.Y), FSlateLayoutTransform(FVector2f(BarPosition))),
		FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
		ESlateDrawEffect::None,
		FLinearColor(0.45f, 0.72f, 0.40f, 1.0f));

	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::Format(FText::FromString(TEXT("Character: {0} | Server: {1}")), GetSelectedCharacterLabel(), JoinServerAddress), FVector2D(ContentX, PanelPosition.Y + (270.0f * Scale)), ContentWidth, BodyFont, FLinearColor(0.78f, 0.84f, 0.72f, 1.0f));
	DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("MVP loading placeholder; final connection and map handoff will attach here.")), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (46.0f * Scale)), ContentWidth, HintFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
}

FText UAgrarianMvpFrontendWidget::GetSelectedCharacterLabel() const
{
	return SelectedCharacterArchetype == EAgrarianMvpCharacterArchetype::YoungAdultFemale
		? FText::FromString(TEXT("young adult female"))
		: FText::FromString(TEXT("young adult male"));
}

void UAgrarianMvpFrontendWidget::DrawTextAt(
	FSlateWindowElementList& OutDrawElements,
	int32& LayerId,
	const FGeometry& AllottedGeometry,
	const FText& Text,
	const FVector2D& Position,
	float Width,
	const FSlateFontInfo& Font,
	const FLinearColor& Color) const
{
	FSlateDrawElement::MakeText(
		OutDrawElements,
		++LayerId,
		AllottedGeometry.ToPaintGeometry(FVector2f(FMath::Max(96.0f, Width), Font.Size + 18.0f), FSlateLayoutTransform(FVector2f(Position))),
		Text,
		Font,
		ESlateDrawEffect::None,
		Color);
}
