#include "UILabel_Base.h"

#include "UIInput_Base.h"
#include "UICommonText_Base.h"
#include "Components/VerticalBox.h"
#include "Components/HorizontalBox.h"
#include "CommonTextBlock.h"

UUIInput_Base* UUILabel_Base::ActiveInput() const
{
	if (LabelLayout == EUIInputLabelLayout::Inline)
	{
		return IsValid(Input_Inline) ? Input_Inline : Input_Stacked;
	}
	return IsValid(Input_Stacked) ? Input_Stacked : Input_Inline;
}

void UUILabel_Base::ApplyLayout()
{
	// Só alterna VISIBILIDADE (nunca muta a árvore — isso crasha em
	// construção/thumbnail do editor).
	const bool bInline = (LabelLayout == EUIInputLabelLayout::Inline);
	if (IsValid(Box_Stacked))
	{
		Box_Stacked->SetVisibility(bInline
			? ESlateVisibility::Collapsed : ESlateVisibility::SelfHitTestInvisible);
	}
	if (IsValid(Row_Inline))
	{
		Row_Inline->SetVisibility(bInline
			? ESlateVisibility::SelfHitTestInvisible : ESlateVisibility::Collapsed);
	}
}

void UUILabel_Base::PropagateInputProps()
{
	auto Apply = [this](UUIInput_Base* In)
	{
		if (!IsValid(In)) { return; }
		// Variant: controle de aparência do UILabel_Base — sempre propaga.
		In->Variant     = Variant;
		// bIsPassword: sempre propaga (controle explícito).
		In->bIsPassword = bIsPassword;
		// Overrides "0/vazio = passthrough": só sobrescreve se o UILabel_Base
		// definiu valor explícito; assim o user pode setar PreferredWidth/Height,
		// FontSize, HintText DIRETO no UI_Input_Master filho e o pai não zera.
		if (FontSize > 0.f)        { In->FontSize        = FontSize; }
		if (!HintText.IsEmpty())   { In->HintText        = HintText; }
		if (PreferredWidth > 0.f)  { In->PreferredWidth  = PreferredWidth; }
		if (PreferredHeight > 0.f) { In->PreferredHeight = PreferredHeight; }
		In->RefreshUIStyle();
	};
	Apply(Input_Stacked);
	Apply(Input_Inline);
}

TArray<FString> UUILabel_Base::GetVariantOptions() const
{
	return UUIInput_Base::CollectVariantOptions();
}

TArray<FString> UUILabel_Base::GetLabelTextRoleOptions() const
{
	return UUICommonText_Base::GetThemeTextRoleOptions();
}

void UUILabel_Base::RefreshUIStyle()
{
	auto SetupLabel = [this](UCommonTextBlock* L)
	{
		if (!L) { return; }
		if (!LabelText.IsEmpty()) { L->SetText(LabelText); }
		if (UUICommonText_Base* CT = Cast<UUICommonText_Base>(L))
		{
			if (CT->TextRole != LabelTextRole) { CT->TextRole = LabelTextRole; }
			CT->RefreshUIStyle();
		}
	};
	SetupLabel(Label_Stacked);
	SetupLabel(Label_Inline);

	PropagateInputProps();
}

FText UUILabel_Base::GetText() const
{
	const UUIInput_Base* In = ActiveInput();
	return In ? In->GetText() : FText::GetEmpty();
}

void UUILabel_Base::SetText(FText InText)
{
	if (UUIInput_Base* In = ActiveInput())
	{
		In->SetText(InText);
	}
}

void UUILabel_Base::SetHintTextRuntime(FText InHint)
{
	HintText = InHint;
	if (IsValid(Input_Stacked)) { Input_Stacked->SetHintTextRuntime(InHint); }
	if (IsValid(Input_Inline))  { Input_Inline->SetHintTextRuntime(InHint); }
}

void UUILabel_Base::SetIsPasswordRuntime(bool bInIsPassword)
{
	bIsPassword = bInIsPassword;
	if (IsValid(Input_Stacked)) { Input_Stacked->SetIsPasswordRuntime(bInIsPassword); }
	if (IsValid(Input_Inline))  { Input_Inline->SetIsPasswordRuntime(bInIsPassword); }
}

void UUILabel_Base::BindInputDelegates()
{
	if (bInputBound) { return; }
	if (IsValid(Input_Stacked))
	{
		Input_Stacked->OnTextChanged.AddDynamic(this, &UUILabel_Base::HandleChildTextChanged);
		Input_Stacked->OnTextCommitted.AddDynamic(this, &UUILabel_Base::HandleChildTextCommitted);
	}
	if (IsValid(Input_Inline))
	{
		Input_Inline->OnTextChanged.AddDynamic(this, &UUILabel_Base::HandleChildTextChanged);
		Input_Inline->OnTextCommitted.AddDynamic(this, &UUILabel_Base::HandleChildTextCommitted);
	}
	bInputBound = true;
}

void UUILabel_Base::UnbindInputDelegates()
{
	if (!bInputBound) { return; }
	if (IsValid(Input_Stacked))
	{
		Input_Stacked->OnTextChanged.RemoveDynamic(this, &UUILabel_Base::HandleChildTextChanged);
		Input_Stacked->OnTextCommitted.RemoveDynamic(this, &UUILabel_Base::HandleChildTextCommitted);
	}
	if (IsValid(Input_Inline))
	{
		Input_Inline->OnTextChanged.RemoveDynamic(this, &UUILabel_Base::HandleChildTextChanged);
		Input_Inline->OnTextCommitted.RemoveDynamic(this, &UUILabel_Base::HandleChildTextCommitted);
	}
	bInputBound = false;
}

void UUILabel_Base::HandleChildTextChanged(const FText& Text)
{
	OnTextChanged.Broadcast(Text);
}

void UUILabel_Base::HandleChildTextCommitted(const FText& Text, ETextCommit::Type CommitMethod)
{
	OnTextCommitted.Broadcast(Text, CommitMethod);
}

void UUILabel_Base::NativePreConstruct()
{
	Super::NativePreConstruct();
	ApplyLayout();
	RefreshUIStyle();
}

void UUILabel_Base::SynchronizeProperties()
{
	Super::SynchronizeProperties();
	ApplyLayout();
	RefreshUIStyle();
}

void UUILabel_Base::NativeConstruct()
{
	Super::NativeConstruct();
	BindInputDelegates();
	ApplyLayout();
	RefreshUIStyle();
}

void UUILabel_Base::NativeDestruct()
{
	UnbindInputDelegates();
	Super::NativeDestruct();
}
