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

#include "LODRecipeEditor.h"
#include "LODRecipe.h"
#include "Customizations/LODRecipeCustomization.h"
#include "LODRecipeEditorToolbarExtender.h"
#include "Customizations/ReductionSettingsCustomization.h"
#include "Customizations/LODRecipeMiscSettingsCustomization.h"
#include "SAllowMorphTargetsWidget.h"

#include "SSingleObjectDetailsPanel.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "PropertyCustomizationHelpers.h"
#include "Widgets/Docking/SDockTab.h"
#include "Telemetry.h"
#include "TelemetryManager.h"


#define LOCTEXT_NAMESPACE "LODRecipeEditor"

const FName LODRecipeEditorAppName = FName(TEXT("LODRecipeEditorApp"));

struct FLODRecipeEditorTabs
{
	static const FName DetailsID;
	static const FName MorphTargetsID;
	static const FName MainID;
};
const FName FLODRecipeEditorTabs::DetailsID(TEXT("Details"));
const FName FLODRecipeEditorTabs::MorphTargetsID(TEXT("AllowMorphTargets"));
const FName FLODRecipeEditorTabs::MainID(TEXT("Main"));

/////////////////////////////////////////////////////
// SSpritePropertiesTabBody

class SLODRecipePropertiesTab : public SSingleObjectDetailsPanel
{
public:
	SLATE_BEGIN_ARGS(SLODRecipePropertiesTab) {}
	SLATE_END_ARGS()

private:
	// Pointer back to owning sprite editor instance (the keeper of state)
	TWeakPtr<FLODRecipeEditor> LODRecipeEditorPtr;
public:
	void Construct(const FArguments& InArgs, TSharedPtr<FLODRecipeEditor> InLODRecipeEditor)
	{
		LODRecipeEditorPtr = InLODRecipeEditor;

		SSingleObjectDetailsPanel::Construct(SSingleObjectDetailsPanel::FArguments().HostCommandList(InLODRecipeEditor->GetToolkitCommands()).HostTabManager(InLODRecipeEditor->GetTabManager()), /*bAutomaticallyObserveViaGetObjectToObserve=*/ true, /*bAllowSearch=*/ true);

		// Register customizations
		FOnGetDetailCustomizationInstance CustomizeLODRecipe = FOnGetDetailCustomizationInstance::CreateStatic(&FLODRecipeDetailsCustomization::MakeInstance);
		PropertyView->RegisterInstancedCustomPropertyLayout(ULODRecipe::StaticClass(), CustomizeLODRecipe);

		FOnGetPropertyTypeCustomizationInstance CustomizeMiscSettings = FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FLODRecipeMiscSettingsCustomization::MakeInstance);
		PropertyView->RegisterInstancedCustomPropertyTypeLayout(FLODRecipeMiscSettings::StaticStruct()->GetFName(), CustomizeMiscSettings);
		/*PropertyView->RegisterInstancedCustomPropertyTypeLayout(
			"ReductionSettings",
			FOnGetPropertyTypeCustomizationInstance::CreateLambda([]() { return MakeShared<FReductionSettingsCustomization>(); }));*/
	}

	// SSingleObjectDetailsPanel interface
	virtual UObject* GetObjectToObserve() const override
	{
		return LODRecipeEditorPtr.Pin()->GetLODRecipeBeingEdited();
	}

	virtual TSharedRef<SWidget> PopulateSlot(TSharedRef<SWidget> PropertyEditorWidget) override
	{
		return SNew(SVerticalBox)
			+ SVerticalBox::Slot()
			.FillHeight(1)
			[
				PropertyEditorWidget
			];
	}
	// End of SSingleObjectDetailsPanel interface

	void ForceRefresh()
	{
		PropertyView->ForceRefresh();
	}
};

FLODRecipeEditor::FLODRecipeEditor()
	: RecipeBeingEdited(nullptr)
{
}

void FLODRecipeEditor::RegisterTabSpawners(const TSharedRef<class FTabManager>& InTabManager)
{
	WorkspaceMenuCategory = InTabManager->AddLocalWorkspaceMenuCategory(LOCTEXT("WorkspaceMenu_LODRecipeEditor", "LOD Recipe Editor"));
	auto WorkspaceMenuCategoryRef = WorkspaceMenuCategory.ToSharedRef();

	FAssetEditorToolkit::RegisterTabSpawners(InTabManager);

	InTabManager->RegisterTabSpawner(FLODRecipeEditorTabs::DetailsID, FOnSpawnTab::CreateSP(this, &FLODRecipeEditor::SpawnTabDetails))
		.SetDisplayName(LOCTEXT("DetailsTabLabel", "Details"))
		.SetGroup(WorkspaceMenuCategoryRef)
		.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Details"));

	// Remove-Morph-Targets tab
	InTabManager->RegisterTabSpawner(FLODRecipeEditorTabs::MorphTargetsID, FOnSpawnTab::CreateSP(this, &FLODRecipeEditor::SpawnTabMorphTargets))
		.SetDisplayName(LOCTEXT("MorphTargetsTabLabel", "Allow Morph Targets"))
		.SetGroup(WorkspaceMenuCategoryRef)
		/*.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Details"))*/;

}

FName FLODRecipeEditor::GetToolkitFName() const
{
	return FName("LODRecipeEditor");
}

FText FLODRecipeEditor::GetBaseToolkitName() const
{
	return LOCTEXT("LODRecitpEditorAppLabel", "LOD Recipe Editor");
}

FText FLODRecipeEditor::GetToolkitName() const
{
	return FText::FromString(RecipeBeingEdited->GetName());
}

FText FLODRecipeEditor::GetToolkitToolTipText() const
{
	return FAssetEditorToolkit::GetToolTipTextForObject(RecipeBeingEdited);
}

FLinearColor FLODRecipeEditor::GetWorldCentricTabColorScale() const
{
	return FLinearColor::White;
}

FString FLODRecipeEditor::GetWorldCentricTabPrefix() const
{
	return TEXT("LODRecipeEditor");
}

FString FLODRecipeEditor::GetDocumentationLink() const
{
	return FString();
}

void FLODRecipeEditor::OnToolkitHostingStarted(const TSharedRef<class IToolkit>& Toolkit)
{
}

void FLODRecipeEditor::OnToolkitHostingFinished(const TSharedRef<class IToolkit>& Toolkit)
{
}

void FLODRecipeEditor::AddReferencedObjects(FReferenceCollector& Collector)
{
	Collector.AddReferencedObject(RecipeBeingEdited);
}

void FLODRecipeEditor::InitLODRecipeEditor(const EToolkitMode::Type Mode, const TSharedPtr<class IToolkitHost>& InitToolkitHost, ULODRecipe* InitLODRecipe)
{
	RecipeBeingEdited = InitLODRecipe;

	FTelemetryBuilder Builder;
	Builder.SetProperties({ FTelemetry::Prop(TEXT("action"), TEXT("init"))
		});
	
	FTelemetry::Record(SGTC::Editor, SGTC::LODRecipe);

	TSharedPtr<FLODRecipeEditor> LODRecipeEditorPtr = SharedThis(this);

	// Default layout
	const TSharedRef<FTabManager::FLayout> StandaloneDefaultLayout = FTabManager::NewLayout("Standalone_LODRecipeEditor_Layout_v6")
		->AddArea
		(
			FTabManager::NewPrimaryArea()
			->SetOrientation(Orient_Vertical)
			->Split
			(
				FTabManager::NewSplitter()
				->SetOrientation(Orient_Horizontal)
				->SetSizeCoefficient(0.6f)
				->Split
				(
					FTabManager::NewStack()
					->SetSizeCoefficient(0.8f)
					->SetHideTabWell(true)
					//->AddTab(FSpriteEditorTabs::ViewportID, ETabState::OpenedTab)
				)
				->Split
				(
					FTabManager::NewSplitter()
					->SetOrientation(Orient_Vertical)
					->SetSizeCoefficient(0.2f)
					->Split
					(
						FTabManager::NewStack()
						->SetSizeCoefficient(0.75f)
						->SetHideTabWell(true)
						->AddTab(FLODRecipeEditorTabs::DetailsID, ETabState::OpenedTab)
					)
					->Split
					(
						FTabManager::NewStack()
						->SetSizeCoefficient(0.25f)
						//->AddTab(FSpriteEditorTabs::SpriteListID, ETabState::OpenedTab)
					)
				)
			)
			->Split
			(
				FTabManager::NewStack()
				->SetSizeCoefficient(0.3f)
				->SetHideTabWell(false)
				->AddTab(FLODRecipeEditorTabs::MorphTargetsID, ETabState::OpenedTab)
			)
		);

	// Initialize the asset editor
	InitAssetEditor(Mode, InitToolkitHost, LODRecipeEditorAppName, StandaloneDefaultLayout, /*bCreateDefaultStandaloneMenu=*/ true, /*bCreateDefaultToolbar=*/ true, InitLODRecipe);

	FSimpleDelegate OnAddMeshes = FSimpleDelegate::CreateLambda([this]() { DetailsTab->ForceRefresh(); });
	AddToolbarExtender(MakeShareable(new FLODRecipeEditorToolbarExtender(RecipeBeingEdited, OnAddMeshes)));
	RegenerateMenusAndToolbars();
}

TSharedRef<SDockTab> FLODRecipeEditor::SpawnTabDetails(const FSpawnTabArgs& Args)
{
	TSharedPtr<FLODRecipeEditor> LODRecipeEditorPtr = SharedThis(this);
	DetailsTab = SNew(SLODRecipePropertiesTab, LODRecipeEditorPtr);

	return SNew(SDockTab)
		.Label(LOCTEXT("DetailsTab_Title", "Details"))
		[
			DetailsTab.ToSharedRef()
		];
}

TSharedRef<SDockTab> FLODRecipeEditor::SpawnTabMorphTargets(const FSpawnTabArgs& Args)
{
	TSharedPtr<FLODRecipeEditor> LODRecipeEditorPtr = SharedThis(this);
	MorphTargetsTab = SNew(SAllowMorphTargetsWidget, GetLODRecipeBeingEdited());

	return SNew(SDockTab)
		.Label(LOCTEXT("MorphTargetsTab_Title", "Allow Morph Targets"))
		[
			MorphTargetsTab.ToSharedRef()
		];
}

#undef LOCTEXT_NAMESPACE
