#include "WingNotifier.h"
#include "Editor.h"
#include "EdGraph/EdGraphNode.h"
#include "EdGraph/EdGraph.h"
#include "Engine/Blueprint.h"
#include "Materials/Material.h"
#include "Materials/MaterialExpression.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "BlueprintEditor.h"
#include "MaterialEditingLibrary.h"
#include "Subsystems/AssetEditorSubsystem.h"
#include "WingHacks.h"

void FWingNotifier::AddTouchedObject(UObject* Obj)
{
	if (!Obj) return;
	bool bAlreadyInSet = false;
	TouchedSet.Add(Obj, &bAlreadyInSet);
	if (bAlreadyInSet) return;
	TouchedArray.Add(Obj);
}

void FWingNotifier::SendNotifications()
{
	UAssetEditorSubsystem* EditorSubsys = GEditor->GetEditorSubsystem<UAssetEditorSubsystem>();
	TSet<UEdGraphNode*> Nodes;
	TSet<UEdGraph*> Graphs;
	TSet<UMaterial*> Materials;
	TSet<UMaterialExpression*> MaterialExpressions;
	TSet<UBlueprint*> Blueprints;
	for (int32 i = TouchedArray.Num() - 1; i >= 0; --i)
	{
		UObject* Obj = TouchedArray[i];
		Obj->MarkPackageDirty();

		if (UEdGraphNode* Node = ::Cast<UEdGraphNode>(Obj))
			Nodes.Add(Node);

		if (UEdGraph* Graph = ::Cast<UEdGraph>(Obj))
			Graphs.Add(Graph);

		if (UBlueprint* BP = ::Cast<UBlueprint>(Obj))
			Blueprints.Add(BP);

		if (UMaterialExpression* Expr = ::Cast<UMaterialExpression>(Obj))
			MaterialExpressions.Add(Expr);

		if (UMaterial* Mat = ::Cast<UMaterial>(Obj))
			Materials.Add(Mat);

		if (UMaterialInterface* MatIface = ::Cast<UMaterialInterface>(Obj))
			if (UMaterial* BaseMat = MatIface->GetMaterial())
				Materials.Add(BaseMat);
	}

	for (UMaterialExpression* Expr : MaterialExpressions)
		Expr->RefreshNode(true);
	// for (UEdGraphNode* Node : Nodes)
	// 	Node->ReconstructNode();
	for (UEdGraph* Graph : Graphs)
		Graph->NotifyGraphChanged();
	for (UMaterial *Material : Materials)
		UMaterialEditingLibrary::RebuildMaterialInstanceEditors(Material);
	for (UBlueprint *Blueprint : Blueprints)
	{
		FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(Blueprint);
		IAssetEditorInstance *Editor = EditorSubsys->FindEditorForAsset(Blueprint, false);
		if (Editor)
		{
			FBlueprintEditor* BPEditor = static_cast<FBlueprintEditor*>(Editor);
			if (WingHacks::WasOpenedInDefaultsMode(BPEditor) && !FBlueprintEditorUtils::IsDataOnlyBlueprint(Blueprint))
			{
				EditorSubsys->CloseAllEditorsForAsset(Blueprint);
				EditorSubsys->OpenEditorForAsset(Blueprint);
			}
		}
	}

	// FBlueprintEditorUtils::RefreshAllNodes(BP);
	// FKismetEditorUtilities::CompileBlueprint(BP);

	if (GEditor)
		GEditor->RedrawAllViewports();

	TouchedSet.Empty();
	TouchedArray.Empty();
}
