// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.

#include "SEdComboActionGraphNode.h"

#include "ComboActionGraph.h"
#include "ComboInputAssets.h"
#include "ComboInputEditor.h"
#include "GraphEditorSettings.h"
#include "SCommentBubble.h"
#include "SGraphPin.h"
#include "SlateOptMacros.h"

#include "Blueprint/UserWidget.h"
#include "Ed/SEdComboActionGraphNodeIndex.h"
#include "Ed/EdComboActionGraphNode.h"
#include "Helpers/ComboActionGraphColors.h"
#include "Nodes/ComboActionGraphNode_ActionNodeBase.h"
#include "Settings/ComboActionGraphEditorSettings.h"
#include "Widgets/Layout/SGridPanel.h"
#include "Widgets/Layout/SScaleBox.h"
#include "Widgets/Text/SInlineEditableTextBlock.h"

#define LOCTEXT_NAMESPACE "EdComboActionGraph"


#pragma region Pin

class SComboActionGraphPin : public SGraphPin
{
public:
	SLATE_BEGIN_ARGS(SComboActionGraphPin) {}
	SLATE_END_ARGS()

	void Construct(const FArguments &InArgs, UEdGraphPin *InPin)
	{
		this->SetCursor(EMouseCursor::Default);

		this->bShowLabel = true;

		this->GraphPinObj = InPin;
		check(this->GraphPinObj != nullptr);

		const UEdGraphSchema *Schema = this->GraphPinObj->GetSchema();
		check(Schema);

		// Pins Out/In Border
		SBorder::Construct(SBorder::FArguments()
			.BorderImage(this, &SComboActionGraphPin::GetPinBorder)
			.BorderBackgroundColor(this, &SComboActionGraphPin::GetPinColor)
			.OnMouseButtonDown(this, &SComboActionGraphPin::OnPinMouseDown)
			.Cursor(this, &SComboActionGraphPin::GetPinCursor)
			.Padding(FMargin(5.0f))
		);
	}

protected:
	virtual FSlateColor GetPinColor() const override
	{
		if (const UComboActionGraphEditorSettings *GraphEditorSettings = GetMutableDefault<UComboActionGraphEditorSettings>())
		{
			switch (GraphEditorSettings->GetNodeTheme())
			{
				case EComboActionNodeTheme::DarkTheme:
					return ComboActionGraphColors::PinsDock::LightTheme;
				case EComboActionNodeTheme::LightTheme:
					return ComboActionGraphColors::PinsDock::DarkTheme;
				default:
					return ComboActionGraphColors::PinsDock::LightTheme;
			} 
		}
		
		return ComboActionGraphColors::Pin::Default;
	}

	virtual TSharedRef<SWidget>	GetDefaultValueWidget() override
	{
		return SNew(STextBlock);
	}

	const FSlateBrush *GetPinBorder() const
	{
		FComboInputEditorModule &ComboInputEditorModule = FComboInputEditorModule::Get();

		if (const UComboActionGraphEditorSettings *GraphEditorSettings = GetMutableDefault<UComboActionGraphEditorSettings>())
		{
			switch (GraphEditorSettings->GetNodeType())
			{
				case EComboActionNodeType::SoftCorners:
					return ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush("MDSStyleSet.Node.TextSoftEdges");
				case EComboActionNodeType::HardCorners:
					return ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush("MDSStyleSet.Node.TextHardEdges");
			}
		}

		return ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush(TEXT("MDSStyleSet.Graph.PinDocksOverlay"));
	}
};

#pragma endregion

void SEdComboActionGraphNode::Construct(const FArguments &InArgs, UEdComboActionGraphNode *InNode)
{
	this->GraphNode = InNode;
	this->UpdateGraphNode();
	InNode->SEdNode = this;
	//bIsHovered = false;
	
	this->GraphEditorSettings = GetMutableDefault<UComboActionGraphEditorSettings>();
}

void SEdComboActionGraphNode::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
	//bIsHovered = true;

	this->SetToolTipText(GetTooltipText());
	this->OnVisualizeTooltip(GetToolTip()->AsWidget());
	
	SGraphNode::OnMouseEnter(MyGeometry, MouseEvent);
}

void SEdComboActionGraphNode::OnMouseLeave(const FPointerEvent& MouseEvent)
{
	//bIsHovered = false;

	this->SetToolTipText(FText::GetEmpty());
	this->OnToolTipClosing();
	
	SGraphNode::OnMouseLeave(MouseEvent);
}

const FSlateBrush *SEdComboActionGraphNode::GetIndexBrush() const
{
	FComboInputEditorModule &ComboInputEditorModule = FComboInputEditorModule::Get();
	return ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush("MDSStyleSet.Node.TextSoftEdges");
}

BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION

void SEdComboActionGraphNode::UpdateGraphNode()
{
	const FMargin NodePadding = FMargin(2.0f);
	const FMargin UnifiedRowsPadding = FMargin(0.f, 1.15f, 0.f, 0.f);

	const FSlateColor DefaultFontColor = ComboActionGraphColors::TextColors::Normal;

	this->InputPins.Empty();
	this->OutputPins.Empty();

	// Reset variables that are going to be exposed, in case we are refreshing an already setup node.
	this->RightNodeBox.Reset();
	this->LeftNodeBox.Reset();
	this->OutputPinBox.Reset();

	TSharedPtr<SErrorText> ErrorText;
	TSharedPtr<SNodeTitle> NodeTitle = SNew(SNodeTitle, this->GraphNode);

	TSharedPtr<SVerticalBox> StackBox;
	TSharedPtr<SVerticalBox> UniformBox;
		
	this->ContentScale.Bind(this, &SGraphNode::GetContentScale);

	FComboInputEditorModule &ComboInputEditorModule = FComboInputEditorModule::Get();
	const FSlateBrush *CircleBrush = ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush(TEXT("MDSStyleSet.Node.IndexCircle"));
	this->GetOrAddSlot(ENodeZone::Left)
	.SlotOffset(TAttribute<FVector2D>(this, &SEdComboActionGraphNode::GetIndexSlotOffset))
	.SlotSize(TAttribute<FVector2D>(this, &SEdComboActionGraphNode::GetIndexSlotSize))
	[
		SNew(SOverlay)
		+SOverlay::Slot()
		.HAlign(EHorizontalAlignment::HAlign_Fill)
		.VAlign(EVerticalAlignment::VAlign_Fill)
		[
			SNew(SBox)
			.WidthOverride(CircleBrush->ImageSize.X)
			.HeightOverride(CircleBrush->ImageSize.Y)
		]

		+SOverlay::Slot()
		.HAlign(EHorizontalAlignment::HAlign_Fill)
		.VAlign(EVerticalAlignment::VAlign_Fill)
		[
			SNew(SBorder)
			.BorderImage(CircleBrush)
			.BorderBackgroundColor(FLinearColor::Gray)
			.Padding(FMargin(4.0f))
			.HAlign(EHorizontalAlignment::HAlign_Center)
			.VAlign(EVerticalAlignment::VAlign_Center)
			[
				SNew(STextBlock)
				.Font(FCoreStyle::GetDefaultFontStyle("Regular", 8))
				.Text(this, &SEdComboActionGraphNode::GetIndexText)
				.Visibility(this, &SEdComboActionGraphNode::GetIndexSlotVisibility)
			]
		]
	];
	
	this->GetOrAddSlot(ENodeZone::Center)
	.HAlign(EHorizontalAlignment::HAlign_Fill)
	.VAlign(EVerticalAlignment::VAlign_Fill)
	[
		SNew(SBox)
		[
			// OUTER STYLE
			SNew(SBorder)
			.BorderImage(this, &SEdComboActionGraphNode::GetNodeTypeBrush)
			.Padding(3.0f)
			.BorderBackgroundColor(this, &SEdComboActionGraphNode::GetBorderBackgroundColor)
			[
				
				SNew(SOverlay)
				
				// Adding some colours so its not so boring
				+ SOverlay::Slot()
				.HAlign(EHorizontalAlignment::HAlign_Fill)
				.VAlign(EVerticalAlignment::VAlign_Fill)
				[
					// INNER STYLE
					SNew(SBorder)
					.BorderImage(this, &SEdComboActionGraphNode::GetNodeTypeBrush)
					.HAlign(EHorizontalAlignment::HAlign_Fill)
					.VAlign(EVerticalAlignment::VAlign_Center)
					.Visibility(EVisibility::SelfHitTestInvisible)
					.BorderBackgroundColor(this, &SEdComboActionGraphNode::GetBorderFrontColor)
				]
				
				// Pins and node details
				+ SOverlay::Slot()
				.HAlign(EHorizontalAlignment::HAlign_Center)
				.VAlign(EVerticalAlignment::VAlign_Fill)
				[
					SNew(SHorizontalBox)

					// INPUT PIN AREA
					+ SHorizontalBox::Slot()
					.AutoWidth()
					[
						SNew(SVerticalBox)
						+ SVerticalBox::Slot()
						.VAlign(EVerticalAlignment::VAlign_Fill)

						+ SVerticalBox::Slot()
						.VAlign(EVerticalAlignment::VAlign_Center)
						[
							SAssignNew(this->LeftNodeBox, SVerticalBox)
						]

						+ SVerticalBox::Slot()
						.VAlign(EVerticalAlignment::VAlign_Fill)
					]

					+ SHorizontalBox::Slot()
					.Padding(FMargin(NodePadding.Left, 0.0f, NodePadding.Right, 0.0f))
					.VAlign(EVerticalAlignment::VAlign_Fill)
					[
						SNew(SVerticalBox)
						+ SVerticalBox::Slot()
						.AutoHeight()
						[
							SAssignNew(this->NodeBody, SBorder)
							.BorderImage(this, &SEdComboActionGraphNode::GetTextNodeTypeBrush)
							.BorderBackgroundColor(this, &SEdComboActionGraphNode::GetNodeTitleBackgroundColor)
							.HAlign(EHorizontalAlignment::HAlign_Fill)
							.VAlign(EVerticalAlignment::VAlign_Center)
							.Visibility(EVisibility::SelfHitTestInvisible)
							[
								SNew(SBox)
								//.MinDesiredWidth(FOptionalSize(145.f))
								[
									SNew(SVerticalBox)
									
									+ SVerticalBox::Slot()
									.AutoHeight()
									[
										SNew(SOverlay)
										+ SOverlay::Slot()
										  .HAlign(EHorizontalAlignment::HAlign_Center)
										  .VAlign(EVerticalAlignment::VAlign_Fill)
										[
											SNew(SVerticalBox)
#pragma region NameSlot
											// NAME SLOT
											+ SVerticalBox::Slot()
											  .AutoHeight()
											  .HAlign(HAlign_Center)
											[
												SNew(SHorizontalBox)
												+ SHorizontalBox::Slot()
												.AutoWidth()
												[
													// POPUP ERROR MESSAGE
													SAssignNew(ErrorText, SErrorText)
													.BackgroundColor(
					                                 this,
					                                 &SEdComboActionGraphNode::GetErrorColor)
													.ToolTipText(
					                                 this,
					                                 &SEdComboActionGraphNode::GetErrorMsgToolTip)
												]
												+ SHorizontalBox::Slot()
												  .AutoWidth()
												  .HAlign(HAlign_Center)
												[
													SNew(SHorizontalBox)
													+ SHorizontalBox::Slot()
													.Padding(FMargin(4.0f, 0.0f, 4.0f, 0.0f))
													[
														SNew(SVerticalBox)
														+ SVerticalBox::Slot()
														  .HAlign(EHorizontalAlignment::HAlign_Center)
														  .AutoHeight()
														[
															SAssignNew(InlineEditableText, SInlineEditableTextBlock)
															.Style(ComboInputEditorModule.GetComboInputEditorStyleSet().Get(), "MDSStyleSet.NodeTitleInlineEditableText")
															.Text(NodeTitle.Get(), &SNodeTitle::GetHeadTitle)
															.OnVerifyTextChanged(
															this, &SEdComboActionGraphNode::OnVerifyNameTextChanged)
															.OnTextCommitted(
															this, &SEdComboActionGraphNode::OnNameTextCommitted)
															.IsReadOnly(this, &SEdComboActionGraphNode::IsNameReadOnly)
															.IsSelected(this, &SEdComboActionGraphNode::IsSelectedExclusively)
															.Justification(ETextJustify::Center)
															.Visibility(EVisibility::Visible)
														]
														
														+ SVerticalBox::Slot()
														.AutoHeight()
														[
															NodeTitle.ToSharedRef()
														]
													]
												]
											]
#pragma endregion 
										]
									]
#pragma region Unified
									+ SVerticalBox::Slot()
									.VAlign(EVerticalAlignment::VAlign_Fill)
									[
										SNew(SBox)
										.Visibility(this, &SEdComboActionGraphNode::GetResponseStackVisibility)
										.HAlign(EHorizontalAlignment::HAlign_Fill)
										[
											SNew(SVerticalBox)
											+ SVerticalBox::Slot()
											[
												SNew(SBox)
												.Visibility(this, &SEdComboActionGraphNode::ShowDecoratorsBottomPadding)
												[
													SNew(SSpacer)
													.Size(FVector2D(0.f, 2.5f))
												]
											]

#pragma region ResponseStack
											// RESPONSE STACK
											+ SVerticalBox::Slot()
											.AutoHeight()
											.HAlign(EHorizontalAlignment::HAlign_Fill)
											.VAlign(EVerticalAlignment::VAlign_Fill)
											.Padding(FMargin(8.0f, 0.0f, 8.0f, 0.0f))
											[
												SNew(SBox)
												.Visibility(EVisibility::Visible)
												.MaxDesiredWidth(FOptionalSize(130.0f))
												.HAlign(EHorizontalAlignment::HAlign_Fill)
												[
													SNew(SHorizontalBox)
													.Visibility(EVisibility::HitTestInvisible)
#pragma region Title
													+ SHorizontalBox::Slot()
													.HAlign(EHorizontalAlignment::HAlign_Center)
													[
														SNew(STextBlock)
														.Text(LOCTEXT("A", "Info:"))
														.Font(FCoreStyle::GetDefaultFontStyle("Bold", 8))
														.ColorAndOpacity(DefaultFontColor)
													]
												]
#pragma endregion
#pragma region Title
												[
													SNew(SVerticalBox)
													.Visibility(EVisibility::HitTestInvisible)

													+ SVerticalBox::Slot()
													.HAlign(EHorizontalAlignment::HAlign_Left)
													[
															SNew(STextBlock)
															.Text(this, &SEdComboActionGraphNode::GetComboInputName)
															.Font(FCoreStyle::GetDefaultFontStyle("Bold", 8))
															.ColorAndOpacity(DefaultFontColor)
													]

													+ SVerticalBox::Slot()
													.HAlign(EHorizontalAlignment::HAlign_Left)
													[
														SNew(STextBlock)
															.Text(this, &SEdComboActionGraphNode::GetComboInputTriggerActionName)
															.Font(FCoreStyle::GetDefaultFontStyle("Bold", 8))
															.ColorAndOpacity(DefaultFontColor)
													]
#pragma endregion
												]
											]
#pragma endregion
											+ SVerticalBox::Slot()
											.HAlign(EHorizontalAlignment::HAlign_Center)
											.VAlign(EVerticalAlignment::VAlign_Fill)
											[
												SNew(SSpacer)
												.Size(FVector2D(0.f, 2.5f))
											]
										]
									]
#pragma endregion 
								]
							]
						]
					]

					+ SHorizontalBox::Slot()
					.AutoWidth()
					[
						SNew(SSpacer)
						.Size(FVector2D(0.0f, 10.0f))
					]
					
					// OUTPUT PIN AREA
					+ SHorizontalBox::Slot()
					.AutoWidth()
					.Padding(20.0f, 0.0f)
					[
						SNew(SVerticalBox)
						+ SVerticalBox::Slot()
						[
							SAssignNew(this->RightNodeBox, SVerticalBox)
							+ SVerticalBox::Slot()
							.HAlign(EHorizontalAlignment::HAlign_Fill)
							.VAlign(EVerticalAlignment::VAlign_Center)
							[
								SAssignNew(this->OutputPinBox, SHorizontalBox)
							]
						]
					]
				]
			]
		]
	];
	
	// Create comment bubble
	TSharedPtr<SCommentBubble> CommentBubble;
	const FSlateColor CommentColor = GetDefault<UGraphEditorSettings>()->DefaultCommentNodeTitleColor;

	SAssignNew(CommentBubble, SCommentBubble)
		.GraphNode(this->GraphNode)
		.Text(this, &SGraphNode::GetNodeComment)
		.OnTextCommitted(this, &SGraphNode::OnCommentTextCommitted)
		.ColorAndOpacity(CommentColor)
		.AllowPinning(true)
		.EnableTitleBarBubble(true)
		.EnableBubbleCtrls(true)
		.GraphLOD(this, &SGraphNode::GetCurrentLOD)
		.IsGraphNodeHovered(this, &SGraphNode::IsHovered);

	GetOrAddSlot(ENodeZone::TopCenter)
		.SlotOffset(TAttribute<FVector2D>(CommentBubble.Get(), &SCommentBubble::GetOffset))
		.SlotSize(TAttribute<FVector2D>(CommentBubble.Get(), &SCommentBubble::GetSize))
		.AllowScaling(TAttribute<bool>(CommentBubble.Get(), &SCommentBubble::IsScalingAllowed))
		.VAlign(EVerticalAlignment::VAlign_Top)
		[
			CommentBubble.ToSharedRef()
		];

	ErrorReporting = ErrorText;
	ErrorReporting->SetError(ErrorMsg);
	CreatePinWidgets();
}

void SEdComboActionGraphNode::CreatePinWidgets()
{
	UEdComboActionGraphNode *StateNode = CastChecked<UEdComboActionGraphNode>(this->GraphNode);

	for (int32 PinIdx = 0; PinIdx < StateNode->Pins.Num(); PinIdx++)
	{
		UEdGraphPin* MyPin = StateNode->Pins[PinIdx];
		if (!MyPin->bHidden)
		{
			TSharedPtr<SGraphPin> NewPin = SNew(SComboActionGraphPin, MyPin);
			
			AddPin(NewPin.ToSharedRef());
		}
	}
}

void SEdComboActionGraphNode::AddPin(const TSharedRef<SGraphPin>& PinToAdd)
{
	PinToAdd->SetOwner(SharedThis(this));

	const UEdGraphPin* PinObj = PinToAdd->GetPinObj();
	const bool bAdvancedParameter = PinObj && PinObj->bAdvancedView;
	if (bAdvancedParameter)
	{
		PinToAdd->SetVisibility( TAttribute<EVisibility>(PinToAdd, &SGraphPin::IsPinVisibleAsAdvanced) );
	}

	if (PinToAdd->GetDirection() == EEdGraphPinDirection::EGPD_Input)
	{
		this->LeftNodeBox->AddSlot()
			.HAlign(HAlign_Fill)
			.VAlign(VAlign_Fill)
			.FillHeight(1.0f)
			.Padding(20.0f,0.0f)
			[
				PinToAdd
			];
		this->InputPins.Add(PinToAdd);
	}
	else // Direction == EEdGraphPinDirection::EGPD_Output
	{
		this->OutputPinBox->AddSlot()
			.HAlign(HAlign_Fill)
			.VAlign(VAlign_Fill)
			.FillWidth(1.0f)
			[
				PinToAdd
			];
		this->OutputPins.Add(PinToAdd);
	}
}

bool SEdComboActionGraphNode::IsNameReadOnly() const
{
	UEdComboActionGraphNode *EdNode_Node = Cast<UEdComboActionGraphNode>(this->GraphNode);
	check(EdNode_Node != nullptr);

	UComboActionGraph *ComboActionGraphNode = EdNode_Node->ComboActionGraphNode->Graph;
	check(this->GraphNode != nullptr);

	return !this->GraphNode->bCanRenameNode || SGraphNode::IsNameReadOnly();
}

END_SLATE_FUNCTION_BUILD_OPTIMIZATION

void SEdComboActionGraphNode::OnNameTextCommitted(const FText& InText, ETextCommit::Type CommitInfo)
{
	if (InText.IsEmpty()) return;
	
	SGraphNode::OnNameTextCommited(InText, CommitInfo);

	UEdComboActionGraphNode *MyNode = CastChecked<UEdComboActionGraphNode>(this->GraphNode);

	if (MyNode != nullptr && MyNode->ComboActionGraphNode != nullptr)
	{
		const FScopedTransaction Transaction(LOCTEXT("ComboActionGraphEditorRenameNode", "Combo Action Editor: Rename Node"));
		MyNode->Modify();
		MyNode->ComboActionGraphNode->Modify();
		MyNode->ComboActionGraphNode->SetNodeTitle(InText);
		UpdateGraphNode();
	}
}

const FSlateBrush *SEdComboActionGraphNode::GetNodeTypeBrush() const
{
	FComboInputEditorModule &ComboInputEditorModule = FComboInputEditorModule::Get();
	if (this->GraphEditorSettings)
	{
		switch (this->GraphEditorSettings->GetNodeType())
		{
			case EComboActionNodeType::SoftCorners:
				return ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush("MDSStyleSet.Node.SoftEdges");
			case EComboActionNodeType::HardCorners: 
				return ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush("MDSStyleSet.Node.HardEdges");
		}
	}

	return ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush("MDSStyleSet.Node.SoftEdges");
}

const FSlateBrush *SEdComboActionGraphNode::GetTextNodeTypeBrush() const
{
	FComboInputEditorModule &ComboInputEditorModule = FComboInputEditorModule::Get();
	if (this->GraphEditorSettings)
	{
		switch (this->GraphEditorSettings->GetNodeType())
		{
		case EComboActionNodeType::SoftCorners:
			return ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush("MDSStyleSet.Node.TextSoftEdges");
		case EComboActionNodeType::HardCorners:
			return ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush("MDSStyleSet.Node.TextHardEdges");
		}
	}

	return ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush("MDSStyleSet.Node.TextSoftEdges");
}

FSlateColor SEdComboActionGraphNode::GetBorderBackgroundColor() const
{
	UEdComboActionGraphNode *MyNode = CastChecked<UEdComboActionGraphNode>(this->GraphNode);
	return MyNode ? MyNode->GetBackgroundColor() : ComboActionGraphColors::NodeBorder::HighlightAbortRange0;
}

FSlateColor SEdComboActionGraphNode::GetBorderFrontColor() const
{
	if (this->GraphEditorSettings)
	{
		switch (this->GraphEditorSettings->GetNodeTheme())
		{
			case EComboActionNodeTheme::DarkTheme:
				return ComboActionGraphColors::Overlay::DarkTheme;
			case EComboActionNodeTheme::LightTheme:
				return ComboActionGraphColors::Overlay::LightTheme;
		} 
	}

	return ComboActionGraphColors::Overlay::DarkTheme;
}

FSlateColor SEdComboActionGraphNode::GetNodeTitleBackgroundColor() const
{
	return ComboActionGraphColors::NodeBody::Default;
}

FSlateColor SEdComboActionGraphNode::GetDecoratorsBackgroundColor() const
{
	return ComboActionGraphColors::DecoratorsBody::Default;
}

FSlateColor SEdComboActionGraphNode::GetPinsDockColor() const
{
	if (this->GraphEditorSettings)
	{
		switch (this->GraphEditorSettings->GetNodeTheme())
		{
		case EComboActionNodeTheme::DarkTheme:
			return  ComboActionGraphColors::PinsDock::DarkTheme;
		case EComboActionNodeTheme::LightTheme:
			return ComboActionGraphColors::PinsDock::LightTheme;
		}
	}

	return ComboActionGraphColors::Overlay::DarkTheme;
}

EVisibility SEdComboActionGraphNode::GetDragOverMarkerVisibility() const
{
	return EVisibility::Visible;
}

const FSlateBrush*SEdComboActionGraphNode::GetNameIcon() const
{
	return FAppStyle::GetBrush(TEXT("BTEditor.Graph.BTNode.Icon"));
}

const FSlateBrush*SEdComboActionGraphNode::GetBulletPointImageBrush() const
{
	FComboInputEditorModule &ComboInputEditorModule = FComboInputEditorModule::Get();
	return ComboInputEditorModule.GetComboInputEditorStyleSet()->GetBrush( "MDSStyleSet.Icon.BulletPoint" );
}

FText SEdComboActionGraphNode::GetIndexOverlayTooltipText() const
{
	return LOCTEXT("NodeIndexTooltip", "Node index");
}

FText SEdComboActionGraphNode::GetIndexText() const
{
	if (const UEdComboActionGraphNode *EdParentNode = Cast<UEdComboActionGraphNode>(GraphNode))
	{
		if (const auto Node = EdParentNode->ComboActionGraphNode)
		{
			if (const auto Graph = Node->Graph)
			{
				const int32 Index = Graph->AllNodes.Find(Node);
				return FText::AsNumber(Index);
			}
			
			return FText::AsNumber(EdParentNode->ComboActionGraphNode->GetNodeIndex());
		}
	}
	return FText::AsNumber(INDEX_NONE);
}

EVisibility SEdComboActionGraphNode::GetIndexSlotVisibility() const
{
	if (this->IsHovered())
	{
		return EVisibility::SelfHitTestInvisible;
	}

	return EVisibility::Collapsed;
}

FVector2D SEdComboActionGraphNode::GetIndexSlotOffset() const
{
	if (this->IsHovered())
	{
		return FVector2D(-20.f);
	}

	return FVector2D(-15.f);
}

FVector2D SEdComboActionGraphNode::GetIndexSlotSize() const
{
	if (this->IsHovered())
	{
		return FVector2D(24.f);
	}

	return FVector2D(12.f);
}

void SEdComboActionGraphNode::OnIndexHoverStateChanged(bool bArg) const
{
	// TODO something
}

FSlateColor SEdComboActionGraphNode::GetOverlayWidgetBackgroundColor(bool bArg) const
{
	return bArg ? ComboActionGraphColors::IndexBorder::HoveredState : ComboActionGraphColors::IndexBorder::NormalState;
}

EVisibility SEdComboActionGraphNode::ShowImplementsOnlySlot_Unified() const
{
	if (this->GraphEditorSettings)
	{
		if (this->GraphEditorSettings->ShowDetailedInfo_NumDecorators() && !this->GraphEditorSettings->ShowDetailedInfo_InheritsDecorators())
		{
			return EVisibility::SelfHitTestInvisible; //return HasGraphDecorators() ? EVisibility::Visible : EVisibility::Collapsed;
		}
	}
	return EVisibility::Collapsed;
}

EVisibility SEdComboActionGraphNode::ShowImplementsOnlySlot_Stack() const
{
	if (this->GraphEditorSettings)
	{
		if (this->GraphEditorSettings->GetDecoratorsStyle() == EComboActionDecoratorsInfoStyle::Stack)
		{
			if (this->GraphEditorSettings->ShowDetailedInfo_NumDecorators())
			{
				return EVisibility::SelfHitTestInvisible; //return HasGraphDecorators() ? EVisibility::Visible : EVisibility::Collapsed;
			}
		}
	}
	return EVisibility::Collapsed;
}

EVisibility SEdComboActionGraphNode::ShowInheritsDecoratorsSlot_Stack() const
{
	if (this->GraphEditorSettings)
	{
		if (this->GraphEditorSettings->GetDecoratorsStyle() == EComboActionDecoratorsInfoStyle::Stack)
		{
			if (this->GraphEditorSettings->ShowDetailedInfo_InheritsDecorators())
			{
				return EVisibility::SelfHitTestInvisible; //return HasGraphDecorators() ? EVisibility::Visible : EVisibility::Collapsed;
			}
		}
	}
	return EVisibility::Collapsed;
}

EVisibility SEdComboActionGraphNode::ShowAllDecorators() const
{
	if (this->GraphEditorSettings)
	{
		if (this->GraphEditorSettings->GetDecoratorsStyle() == EComboActionDecoratorsInfoStyle::Unified)
		{
			if (this->GraphEditorSettings->ShowDetailedInfo_InheritsDecorators() && this->GraphEditorSettings->ShowDetailedInfo_NumDecorators())
			{
				return EVisibility::SelfHitTestInvisible; //return HasGraphDecorators() ? EVisibility::Visible : EVisibility::Collapsed;
			}
		}
	}
	return EVisibility::Collapsed;
}

EVisibility SEdComboActionGraphNode::ShowDecoratorsBottomPadding() const
{
	if (this->GraphEditorSettings)
	{
		if (this->GraphEditorSettings->ShowDetailedInfo_InheritsDecorators() || this->GraphEditorSettings->ShowDetailedInfo_NumDecorators())
		{
			return EVisibility::SelfHitTestInvisible;
		}
	}
	return EVisibility::Collapsed;
}

EComboActionDecoratorsInfoStyle SEdComboActionGraphNode::GetDecoratorsStyle() const
{
	if (this->GraphEditorSettings)
	{
		return this->GraphEditorSettings->GetDecoratorsStyle();
	}

	if (const UComboActionGraphEditorSettings *TempSettings = GetMutableDefault<UComboActionGraphEditorSettings>())
	{
		return TempSettings->GetDecoratorsStyle();
	}

	return EComboActionDecoratorsInfoStyle::Stack;
}

EVisibility SEdComboActionGraphNode::GetResponseStackVisibility() const
{
	if (const UEdComboActionGraphNode *EdParentNode = Cast<UEdComboActionGraphNode>(this->GraphNode))
	{
		if (const UComboActionGraphNode_ActionNodeBase *ActionNode = Cast<UComboActionGraphNode_ActionNodeBase>(EdParentNode->ComboActionGraphNode))
		{
			return EVisibility::SelfHitTestInvisible;
		}
	}
	return EVisibility::Collapsed;
}

FText SEdComboActionGraphNode::GetTooltipText() const
{
	if (const UEdComboActionGraphNode *EdParentNode = Cast<UEdComboActionGraphNode>(this->GraphNode))
	{
		return EdParentNode->GetTooltipText();
	}
	return LOCTEXT("SEdComboActionGraphNode_Tooltip", "invalid node selected");
}

FText SEdComboActionGraphNode::GetComboInputName() const
{
	if (const UEdComboActionGraphNode *EdParentNode = Cast<UEdComboActionGraphNode>(this->GraphNode))
	{
		if (const UComboActionGraphNode_ActionNodeBase *ActionNode = Cast<UComboActionGraphNode_ActionNodeBase>(EdParentNode->ComboActionGraphNode))
		{
			if (UComboInputAsset *ComboInput = ActionNode->GetComboInput())
			{
				return FText::FromName(ComboInput->ComboInputName);
			}
			return LOCTEXT("SEdComboActionGraphNode_ComboInputNull", "No Combo Input set");
		}
	}
	return LOCTEXT("SEdComboActionGraphNode_ComboInputNameNotSet", "unset");
}

FText SEdComboActionGraphNode::GetComboInputTriggerActionName() const
{
	if (const UEdComboActionGraphNode *EdParentNode = Cast<UEdComboActionGraphNode>(this->GraphNode))
	{
		if (const UComboActionGraphNode_ActionNodeBase *ActionNode = Cast<UComboActionGraphNode_ActionNodeBase>(EdParentNode->ComboActionGraphNode))
		{
			const FString &EnumNameString = StaticEnum<EComboActionTriggerEvent>()->GetNameByValue((uint8)ActionNode->GetTriggerEvent()).ToString();
			FString EnumType, EnumValueName;
			EnumNameString.Split("::", &EnumType, &EnumValueName);
			return FText::FromString(EnumValueName);
		}
	}
	return LOCTEXT("SEdComboActionGraphNode_TriggerActionNameNotSet", "unset");
}

#undef LOCTEXT_NAMESPACE
