// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT license.

#pragma once
#include "DragAndDrop/ActorDragDropGraphEdOp.h"
#include "StandinActionType.h"

class AStandInMeshActor;

namespace StandInsOutliner
{
	struct ITreeItem;
	typedef TSharedPtr<ITreeItem> FTreeItemPtr;

	/** Consilidated drag/drop information parsed for the HLOD outliner */
	struct FDragDropPayload
	{
		/** Default constructor, resulting in unset contents */
		FDragDropPayload();

		/** Populate this payload from an array of tree items */
		template<typename TItem>
		FDragDropPayload(const TArray<TItem>& InDraggedItems)
		{
			for (const auto& Item : InDraggedItems)
			{
				Item->PopulateDragDropPayload(*this);
			}
		}

		/** Optional array of dragged static mesh actors */
		TOptional<TArray<TWeakObjectPtr<AActor>>> StaticMeshActors;

		/** Optional array of dragged replacement lod actors */
		TOptional<TArray<TWeakObjectPtr<AActor>>> StandinLODActors;

		/** Optional array of dragged actors tagged with SimplygonUserData */
		TOptional<TArray<TWeakObjectPtr<AActor>>> TaggedActors;

		/** Flag whether or not this is a drop coming from the SceneOutliner or within the HLOD Outliner */
		bool bSceneOutliner;

		/** World instance that is being used for the HLOD Outliner */
		UWorld* OutlinerWorld;

		/**
		*	Parse a drag operation into our list of actors and folders
		*	@return true if the operation is viable for the HLOD outliner to process, false otherwise
		*/
		bool ParseDrag(const FDragDropOperation& Operation);
	};

	/** Construct a new Drag and drop operation for a scene outliner */
	TSharedPtr<FDragDropOperation> CreateDragDropOperation(const TArray<FTreeItemPtr>& InTreeItems);

	/** A drag/drop operation that was started from the scene outliner */
	struct FStandInsOutlinerDragDropOp : public FDragDropOperation
	{
		enum ToolTipIconType
		{
			ToolTip_Compatible,
			ToolTip_Incompatible,
			ToolTip_MultipleSelection_Compatible,
			ToolTip_MultipleSelection_Incompatible
		};

		DRAG_DROP_OPERATOR_TYPE(FStandInsOutlinerDragDropOp, FDragDropOperation);

		FStandInsOutlinerDragDropOp(const FDragDropPayload& DraggedObjects);

		using FDragDropOperation::Construct;

		/** Actor drag operation */
		TSharedPtr<FActorDragDropOp>	StaticMeshActorOp;
		TSharedPtr<FActorDragDropOp>	StandinActorOp;

		void ResetTooltip()
		{
			OverrideText = FText();
			OverrideIcon = nullptr;
		}

		void SetTooltip(FText InOverrideText, const FSlateBrush* InOverrideIcon)
		{
			OverrideText = InOverrideText;
			OverrideIcon = InOverrideIcon;
		}

		virtual TSharedPtr<SWidget> GetDefaultDecorator() const override;

	private:

		EVisibility GetOverrideVisibility() const;
		EVisibility GetDefaultVisibility() const;

		FText OverrideText;
		FText GetOverrideText() const { return OverrideText; }

		const FSlateBrush* OverrideIcon;
		const FSlateBrush* GetOverrideIcon() const { return OverrideIcon; }
	};

	/** Struct used for validation of a drag/drop operation in the scene outliner */
	struct FDragValidationInfo
	{
		/** The tooltip type to display on the operation */
		FStandInsOutlinerDragDropOp::ToolTipIconType TooltipIconType;

		/** The tooltip text to display on the operation */
		FText ValidationText;

		EStandInsOutlinerActionType ActionType;

		/** Construct this validation information out of a tooltip type and some text */
		FDragValidationInfo(const EStandInsOutlinerActionType InActionType, const FStandInsOutlinerDragDropOp::ToolTipIconType InTooltipIconType, const FText InValidationText)
			: TooltipIconType(InTooltipIconType)
			, ValidationText(InValidationText)
			, ActionType(InActionType)
		{
		}

		/** Return a generic invalid result */
		static FDragValidationInfo Invalid()
		{
			return FDragValidationInfo(EStandInsOutlinerActionType::InvalidAction, FStandInsOutlinerDragDropOp::ToolTip_Incompatible, FText());
		}

		/** @return true if this operation is valid, false otherwise */
		bool IsValid() const
		{
			switch (TooltipIconType)
			{
			case FStandInsOutlinerDragDropOp::ToolTip_Compatible:
			case FStandInsOutlinerDragDropOp::ToolTip_MultipleSelection_Compatible:
				return true;
			default:
				return false;
			}
		}
	};
};
