#pragma once

#include "CoreMinimal.h"
#include "WingServer.h"
#include "WingBasics.h"
#include "WingFetcher.h"
#include "WingUtils.h"
#include "WidgetBlueprint.h"
#include "Blueprint/WidgetTree.h"
#include "Components/PanelWidget.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "Widget_Remove.generated.h"


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------

UCLASS()
class UWing_Widget_Remove : public UWingHandler
{
	GENERATED_BODY()

public:
	UPROPERTY(EditAnywhere, meta=(Description="Path to the widget, eg /Game/Widgets/WB_Test,widget:MyButton"))
	FString WidgetPath;

	virtual void Register() override
	{
		UWingServer::AddHandler(this,
			TEXT("Delete a widget from a Widget Blueprint's widget tree. "
			"The widget must not have any children."));
	}
	virtual void Handle() override
	{
		// Walk to the widget.
		WingFetcher F(WingOut::Stdout);
		UWidget* TargetWidget = F.Walk(WidgetPath).Cast<UWidget>();
		if (!TargetWidget) return;

		// Get the widget blueprint and tree from the widget's outer chain.
		UWidgetBlueprint* BP = TargetWidget->GetTypedOuter<UWidgetBlueprint>();
		if (!BP)
		{
			WingOut::Stdout.Printf(TEXT("ERROR: Could not find owning WidgetBlueprint\n"));
			return;
		}
		UWidgetTree* Tree = BP->WidgetTree;

		// If it's a panel, make sure it has no children.
		if (UPanelWidget* Panel = Cast<UPanelWidget>(TargetWidget))
		{
			if (Panel->GetChildrenCount() > 0)
			{
				WingOut::Stdout.Printf(TEXT("ERROR: Widget '%s' has %d children. Remove them first.\n"),
					*WingUtils::FormatName(TargetWidget), Panel->GetChildrenCount());
				return;
			}
		}

		FString WidgetName = WingUtils::FormatName(TargetWidget);

		// Remove delegate bindings that reference this widget.
		FString WidgetObjName = TargetWidget->GetName();
		for (int32 i = BP->Bindings.Num() - 1; i >= 0; i--)
		{
			if (BP->Bindings[i].ObjectName == WidgetObjName)
				BP->Bindings.RemoveAt(i);
		}

		// Remove the widget from the tree.
		Tree->RemoveWidget(TargetWidget);

		// Remove variable nodes from the blueprint graph if this was a variable.
		if (TargetWidget->bIsVariable)
		{
			FBlueprintEditorUtils::RemoveVariableNodes(BP, TargetWidget->GetFName());
		}

		// Rename to transient package to avoid name conflicts with future widgets.
		TargetWidget->Rename(nullptr, GetTransientPackage());

		WingOut::Stdout.Printf(TEXT("Deleted widget '%s'\n"), *WidgetName);
	}
};
