#pragma once

#include "CoreMinimal.h"
#include "WingServer.h"
#include "WingBasics.h"
#include "WingFactories.h"
#include "SysInfo_Factories.generated.h"


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

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

public:
	virtual void Register() override
	{
		UWingServer::AddHandler(this,
			TEXT("Sysinfo commands are intended for the human who "
			"is developing this plugin, they help him to understand. "
			"unreal's internals better."));
	}

	virtual void Handle() override
	{
		// Build a set of factory classes that are already supported by Create commands.
		TSet<UClass*> SupportedFactories;
		for (const FWingHandlerConfig& H : UWingServer::AllHandlers())
		{
			if (H.Kind != EWingHandlerKind::Create) continue;
			if (H.FactoryClass.IsValid())
				SupportedFactories.Add(H.FactoryClass.Get());
		}

		TArray<UClass*> FactoryClasses;
		GetDerivedClasses(UFactory::StaticClass(), FactoryClasses);

		TArray<FString> Supported;
		TArray<FString> Unsupported;

		for (UClass *Factory : FactoryClasses)
		{
			if (!WingFactories::CanCreate(Factory)) continue;
			TArray<FName> Params = WingFactories::GetParameterNames(Factory);
			TStringBuilder<512> Line;
			Line.Appendf(TEXT("%2d %s  "), Params.Num(), *Factory->GetName());
			for (const FName& Prop : Params)
				Line.Appendf(TEXT(" %s"), *Prop.ToString());
			if (SupportedFactories.Contains(Factory))
				Supported.Add(Line.ToString());
			else
				Unsupported.Add(Line.ToString());
		}

		Supported.Sort();
		Unsupported.Sort();

		WingOut::Stdout.Print(TEXT("SUPPORTED:\n"));
		for (const FString &Line : Supported)
			WingOut::Stdout.Printf(TEXT("%s\n"), *Line);

		WingOut::Stdout.Print(TEXT("\nUNSUPPORTED:\n"));
		for (const FString &Line : Unsupported)
			WingOut::Stdout.Printf(TEXT("%s\n"), *Line);
	}
};
