#pragma once

#include "CoreMinimal.h"
#include "WingActorComponent.generated.h"

class UBlueprint;
class USCS_Node;
class UActorComponent;
class USimpleConstructionScript;

// a 'Component Reference' is basically just a pointer to a
// blueprint plus a component name.  The other fields in here
// are purely for convenience of printing things out, they
// are *never* used for any analysis.
//
UCLASS()
class UWingComponentReference : public UObject
{
	GENERATED_BODY()
public:
	// The blueprint that was queried: not necessarily the
	// same blueprint that defined the component.
	UPROPERTY()
	UBlueprint* BP = nullptr;
	
	// The component name.
	FName VariableName;

	// Externalized Parent Name (for display only)
	FString ParentName;

	// Externalized TypeName of the component (for display only)
	FString TypeName;

	// True if the component is native (for display only)
	bool Native = false;

	// True if the component was inherited (for display only)
	bool Inherited = false;

	UActorComponent* GetImmutableTemplate() const;
	UActorComponent* GetMutableTemplate() const;

	bool ReparentComponent(UWingComponentReference *Parent);
	bool DeleteComponent();
	static bool AddComponent(UBlueprint *BP, UClass *Class, UWingComponentReference *Parent, FName Name);

	static TArray<UWingComponentReference*> GetAll(UBlueprint* BP);

	static bool CheckValidComponentClass(UClass *Class);
private:
	struct FoundComponent
	{
		FName Name;
		USCS_Node *SCS;
		UActorComponent *Native;
	};

	static UActorComponent *FindComponentInCDO(UClass *Class, FName Name);
	static USCS_Node* FindSCSNodeByName(UBlueprint *BP, FName VariableName);
	static FoundComponent FindComponent(UBlueprint *BP, FName Name);
	static bool CheckValidParent(FoundComponent FC);
	static bool CheckExists(FoundComponent FC);
	static bool CheckNoSuchComponent(FoundComponent FC);
	static bool CheckNotNative(FoundComponent FC, const TCHAR *Action);
	static bool CheckOwnedByBlueprint(FoundComponent FC, UBlueprint *BP);
	static void AddChildNode(UBlueprint *BP, USCS_Node *Node, FoundComponent Parent);
	static TMap<FName, FName> CalculateParentNames(USimpleConstructionScript *Script);
};

