// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#include "PolishBuildingsPrivatePCH.h"
#include "SBuildingsProxyDialog.h"
#include "Dialogs/DlgPickAssetPath.h"
#include "SNumericEntryBox.h"
#include "STextComboBox.h"
#include "BuildingsProxyTool/BuildingsProxyTool.h"

#define LOCTEXT_NAMESPACE "SBuildingsProxyDialog"


void SBuildingsProxyDialog::Construct(const FArguments& InArgs, FBuildingsProxyTool* InTool)
{
	Tool = InTool;
	check(Tool != nullptr);

	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("+X"))));
	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("+Y"))));
	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("+Z"))));
	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("-X"))));
	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("-Y"))));
	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("-Z"))));

	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("64"))));
	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("128"))));
	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("256"))));
	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("512"))));
	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("1024"))));
	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("2048"))));

	CreateLayout();
}

BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SBuildingsProxyDialog::CreateLayout()
{
	int32 TextureResEntryIndex = FindTextureResolutionEntryIndex( Tool->ProxySettings.MaterialSettings.TextureSize.X );
	int32 LightMapResEntryIndex = FindTextureResolutionEntryIndex( Tool->ProxySettings.LightMapResolution );
	TextureResEntryIndex = FMath::Max( TextureResEntryIndex, 0 );
	LightMapResEntryIndex = FMath::Max( LightMapResEntryIndex, 0 );

	this->ChildSlot
	[
		SNew(SVerticalBox)
			
		+SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		.Padding(10)
		[
			// Simplygon logo
			SNew(SImage)
			.Image(FEditorStyle::GetBrush("BuildingsProxy.SimplygonLogo"))
		]
			
		+SVerticalBox::Slot()
		.AutoHeight()
		[
			SNew(SBorder)
			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
			[
				// Proxy options
				SNew(SVerticalBox)

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew(SHorizontalBox)
					+SHorizontalBox::Slot()
					.FillWidth(0.5f)
					.VAlign(VAlign_Center)
					[
						SNew(STextBlock)
						.Text(LOCTEXT("OnScreenSizeLabel", "On Screen Size (pixels)"))
						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
						.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, ScreenSize ) ) )
					]
					+ SHorizontalBox::Slot()
					.FillWidth(0.5f)
					.HAlign(HAlign_Left)
					.VAlign(VAlign_Center)
					[
						SNew(SBox)
						.HAlign(HAlign_Fill)
						.MinDesiredWidth(100.0f)
						.MaxDesiredWidth(100.0f)
						[
							SNew(SNumericEntryBox<int32>)
							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
							.MinValue(40)
							.MaxValue(1200)
							.MinSliderValue(40)
							.MaxSliderValue(1200)
							.AllowSpin(true)
							.Value(this, &SBuildingsProxyDialog::GetScreenSize)
							.OnValueChanged(this, &SBuildingsProxyDialog::ScreenSizeChanged)
						]
					]
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew(SHorizontalBox)
					+SHorizontalBox::Slot()
					.FillWidth(0.5f)
					.VAlign(VAlign_Center)
					[
						SNew(STextBlock)
						.Text(LOCTEXT("MergeDistanceLabel", "Merge Distance (pixels)"))
						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
						.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, MergeDistance ) ) )
					]
					+ SHorizontalBox::Slot()
					.FillWidth(0.5f)
					.HAlign(HAlign_Left)
					.VAlign(VAlign_Center)
					[
						SNew(SBox)
						.HAlign(HAlign_Fill)
						.MinDesiredWidth(100.0f)
						.MaxDesiredWidth(100.0f)
						[
							SNew(SNumericEntryBox<int32>)
							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
							.MinValue(0)
							.MaxValue(300)
							.MinSliderValue(0)
							.MaxSliderValue(300)
							.AllowSpin(true)
							.Value(this, &SBuildingsProxyDialog::GetMergeDistance)
							.OnValueChanged(this, &SBuildingsProxyDialog::MergeDistanceChanged)
						]
					]
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew(SHorizontalBox)
					+SHorizontalBox::Slot()
					.FillWidth(0.5f)
					.VAlign(VAlign_Center)
					[
						SNew(STextBlock)
						.Text(LOCTEXT("TextureResolutionLabel", "Texture Resolution"))
						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
					]
					+ SHorizontalBox::Slot()
					.FillWidth(0.5f)
					.HAlign(HAlign_Left)
					.VAlign(VAlign_Center)
					[
						SNew(STextComboBox)
						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
						.OptionsSource(&TextureResolutionOptions)
						.InitiallySelectedItem( TextureResolutionOptions[TextureResEntryIndex] )
						.OnSelectionChanged(this, &SBuildingsProxyDialog::SetTextureResolution)
					]
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew( SHorizontalBox )
					+ SHorizontalBox::Slot()
					.FillWidth( 0.5f )
					.VAlign( VAlign_Center )
					[
						SNew(STextBlock)
						.Text( LOCTEXT( "LightMapResolutionLabel", "LightMap Resolution" ) )
						.Font( FEditorStyle::GetFontStyle( "StandardDialog.SmallFont" ) )
						.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, LightMapResolution ) ) )
					]
					+ SHorizontalBox::Slot()
					.FillWidth( 0.5f )
					.HAlign( HAlign_Left )
					.VAlign( VAlign_Center )
					[
						SNew( STextComboBox )
						.Font( FEditorStyle::GetFontStyle( "StandardDialog.SmallFont" ) )
						.OptionsSource( &TextureResolutionOptions )
						.InitiallySelectedItem( TextureResolutionOptions[LightMapResEntryIndex] )
						.OnSelectionChanged( this, &SBuildingsProxyDialog::SetLightMapResolution )
					]
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew(SHorizontalBox)
					+SHorizontalBox::Slot()
					.FillWidth(0.5f)
					.VAlign(VAlign_Center)
					.Padding(0.0, 0.0, 3.0, 0.0)
					[
						SNew( STextBlock )
						.Text( LOCTEXT( "HardAngleLabel", "Hard Edge Angle" ) )
						.Font( FEditorStyle::GetFontStyle( "StandardDialog.SmallFont" ) )
						.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, HardAngleThreshold ) ) )
					]
					+SHorizontalBox::Slot()
					.FillWidth(0.5f)
					.HAlign(HAlign_Left)
					.VAlign(VAlign_Center)
					[
						SNew(SBox)
						.HAlign(HAlign_Fill)
						.MinDesiredWidth(100.0f)
						.MaxDesiredWidth(100.0f)
						[
							SNew(SNumericEntryBox<float>)
							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
							.MinValue(0.f)
							.MaxValue(180.f)
							.MinSliderValue(0.f)
							.MaxSliderValue(180.f)
							.AllowSpin(true)
							.Value(this, &SBuildingsProxyDialog::GetHardAngleThreshold)
							.OnValueChanged(this, &SBuildingsProxyDialog::HardAngleThresholdChanged)
							.IsEnabled(this, &SBuildingsProxyDialog::HardAngleThresholdEnabled)
						]
					]
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew(SCheckBox)
					.Type(ESlateCheckBoxType::CheckBox)
					.IsChecked( this, &SBuildingsProxyDialog::GetRecalculateNormals )
					.OnCheckStateChanged( this, &SBuildingsProxyDialog::SetRecalculateNormals )
					.Content()
					[
						SNew( STextBlock )
						.Text( LOCTEXT( "RecalcNormalsLabel", "Recalculate Normals" ) )
						.Font( FEditorStyle::GetFontStyle( "StandardDialog.SmallFont" ) )
						.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, bRecalculateNormals ) ) )
					]
				]

				+ SVerticalBox::Slot()
				.AutoHeight()
				.Padding( FEditorStyle::GetMargin( "StandardDialog.ContentPadding" ) )
				[
					SNew( SCheckBox )
					.Type( ESlateCheckBoxType::CheckBox )
					.IsChecked(this, &SBuildingsProxyDialog::GetUseClippingPlane)
					.OnCheckStateChanged(this, &SBuildingsProxyDialog::SetUseClippingPlane)
					.Content()
					[
						SNew(STextBlock)
						.Text(LOCTEXT("ClippingPlaneLabel", "Use Clipping Plane"))
						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
					]
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew(SHorizontalBox)
					+SHorizontalBox::Slot()
					.VAlign(VAlign_Center)
					.FillWidth(0.5f)
					[
						SNew(SHorizontalBox)
						+SHorizontalBox::Slot()
						.AutoWidth()
						[
							SNew(SBox)
							.MinDesiredWidth(30)
							[
								SNullWidget::NullWidget
							]
						]
						+SHorizontalBox::Slot()
						.AutoWidth()
						.HAlign(HAlign_Left)
						[
							SNew(STextBlock)
							.IsEnabled(this, &SBuildingsProxyDialog::UseClippingPlaneEnabled)
							.Text(LOCTEXT("ClippingAxisLabel", "Clipping Axis"))
							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
							.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, AxisIndex ) ) )
						]
					]
					+SHorizontalBox::Slot()
					.FillWidth(0.5f)
					.HAlign(HAlign_Left)
					.VAlign(VAlign_Center)
					.Padding(8.0, 0.0, 8.0, 0.0)
					[
						SNew(STextComboBox)
						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
						.OptionsSource(&CuttingPlaneOptions)
						.InitiallySelectedItem(CuttingPlaneOptions[0])
						.OnSelectionChanged(this, &SBuildingsProxyDialog::SetClippingAxis)
						.IsEnabled(this, &SBuildingsProxyDialog::UseClippingPlaneEnabled)
					]
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew(SHorizontalBox)
					+SHorizontalBox::Slot()
					.FillWidth(0.5f)
					.VAlign(VAlign_Center)
					.Padding(0.0, 0.0, 3.0, 0.0)
					[
						SNew(SHorizontalBox)
						+SHorizontalBox::Slot()
						.AutoWidth()
						[
							SNew(SBox)
							.MinDesiredWidth(30)
							[
								SNullWidget::NullWidget
							]
						]
						+SHorizontalBox::Slot()
						.HAlign(HAlign_Left)
						.AutoWidth()
						[
							SNew(STextBlock)
							.Text(LOCTEXT("PlaneLevelLabel", "Plane level"))
							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
							.IsEnabled(this, &SBuildingsProxyDialog::UseClippingPlaneEnabled)
							.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, ClippingLevel ) ) )
						]
					]
					+SHorizontalBox::Slot()
					.FillWidth(0.5f)
					.HAlign(HAlign_Left)
					[
						SNew(SBox)
						.HAlign(HAlign_Fill)
						.MinDesiredWidth(100.0f)
						.MaxDesiredWidth(100.0f)
						[
							SNew(SNumericEntryBox<float>)
							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
							.Value(this, &SBuildingsProxyDialog::GetClippingLevel)
							.OnValueChanged(this, &SBuildingsProxyDialog::ClippingLevelChanged)
							.IsEnabled(this, &SBuildingsProxyDialog::UseClippingPlaneEnabled)
						]
					]
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew(SCheckBox)
					.Type(ESlateCheckBoxType::CheckBox)
					.IsChecked(this, &SBuildingsProxyDialog::GetExportNormalMap)
					.OnCheckStateChanged(this, &SBuildingsProxyDialog::SetExportNormalMap)
					.Content()
					[
						SNew(STextBlock)
						.Text(LOCTEXT("ExportNormalMapLabel", "Export Normal Map"))
						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
					]
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew(SCheckBox)
					.Type(ESlateCheckBoxType::CheckBox)
					.IsChecked(this, &SBuildingsProxyDialog::GetExportMetallicMap)
					.OnCheckStateChanged(this, &SBuildingsProxyDialog::SetExportMetallicMap)
					.Content()
					[
						SNew(STextBlock)
						.Text(LOCTEXT("ExportMetallicMapLabel", "Export Metallic Map"))
						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
					]
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew(SCheckBox)
					.Type(ESlateCheckBoxType::CheckBox)
					.IsChecked(this, &SBuildingsProxyDialog::GetExportRoughnessMap)
					.OnCheckStateChanged(this, &SBuildingsProxyDialog::SetExportRoughnessMap)
					.Content()
					[
						SNew(STextBlock)
						.Text(LOCTEXT("ExportRoughnessMapLabel", "Export Roughness Map"))
						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
					]
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding"))
				[
					SNew(SCheckBox)
					.Type(ESlateCheckBoxType::CheckBox)
					.IsChecked(this, &SBuildingsProxyDialog::GetExportSpecularMap)
					.OnCheckStateChanged(this, &SBuildingsProxyDialog::SetExportSpecularMap)
					.Content()
					[
						SNew(STextBlock)
						.Text(LOCTEXT("ExportSpecularMapLabel", "Export Specular Map"))
						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont"))
					]
				]
			]
		]
	];
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

int32 SBuildingsProxyDialog::FindTextureResolutionEntryIndex( int32 InResolution ) const
{
	FString ResolutionStr = TTypeToString<int32>::ToString( InResolution );

	int32 Result = TextureResolutionOptions.IndexOfByPredicate( [&]( const TSharedPtr<FString>& Entry )
	{
		return ( ResolutionStr == *Entry );
	} );

	return Result;
}

FText SBuildingsProxyDialog::GetPropertyToolTipText( const FName& PropertyName ) const
{
	UProperty* Property = FMeshProxySettings::StaticStruct()->FindPropertyByName( PropertyName );
	if ( Property )
	{
		return Property->GetToolTipText();
	}

	return FText::GetEmpty();
}

//Screen size
TOptional<int32> SBuildingsProxyDialog::GetScreenSize() const
{
	return Tool->ProxySettings.ScreenSize;
}

void SBuildingsProxyDialog::ScreenSizeChanged(int32 NewValue)
{
	Tool->ProxySettings.ScreenSize = NewValue;
}

//Recalculate normals
ECheckBoxState SBuildingsProxyDialog::GetRecalculateNormals() const
{
	return Tool->ProxySettings.bRecalculateNormals ? ECheckBoxState::Checked: ECheckBoxState::Unchecked;
}

void SBuildingsProxyDialog::SetRecalculateNormals(ECheckBoxState NewValue)
{
	Tool->ProxySettings.bRecalculateNormals = (NewValue == ECheckBoxState::Checked);
}

//Hard Angle Threshold
bool SBuildingsProxyDialog::HardAngleThresholdEnabled() const
{
	if(Tool->ProxySettings.bRecalculateNormals)
	{
		return true;
	}

	return false;
}

TOptional<float> SBuildingsProxyDialog::GetHardAngleThreshold() const
{
	return Tool->ProxySettings.HardAngleThreshold;
}

void SBuildingsProxyDialog::HardAngleThresholdChanged(float NewValue)
{
	Tool->ProxySettings.HardAngleThreshold = NewValue;
}

//Merge Distance
TOptional<int32> SBuildingsProxyDialog::GetMergeDistance() const
{
	return Tool->ProxySettings.MergeDistance;
}

void SBuildingsProxyDialog::MergeDistanceChanged(int32 NewValue)
{
	Tool->ProxySettings.MergeDistance = NewValue;
}

//Clipping Plane
ECheckBoxState SBuildingsProxyDialog::GetUseClippingPlane() const
{
	return Tool->ProxySettings.bUseClippingPlane ? ECheckBoxState::Checked: ECheckBoxState::Unchecked;
}

void SBuildingsProxyDialog::SetUseClippingPlane(ECheckBoxState NewValue)
{
	Tool->ProxySettings.bUseClippingPlane = (NewValue == ECheckBoxState::Checked);
}

bool SBuildingsProxyDialog::UseClippingPlaneEnabled() const
{
	if(Tool->ProxySettings.bUseClippingPlane)
	{
		return true;
	}
	return false;
}

void SBuildingsProxyDialog::SetClippingAxis(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo )
{
	//This is a ugly hack, but it solves the problem for now
	int32 AxisIndex = CuttingPlaneOptions.Find(NewSelection);
	//FMessageDialog::Debugf(*FString::Printf(TEXT("%d"), AxisIndex ));
	if(AxisIndex < 3)
	{
		Tool->ProxySettings.bPlaneNegativeHalfspace = false;
		Tool->ProxySettings.AxisIndex = AxisIndex;
		return;
	}
	else
	{
		Tool->ProxySettings.bPlaneNegativeHalfspace = true;
		Tool->ProxySettings.AxisIndex = AxisIndex - 3;
		return;
	}
}

TOptional<float> SBuildingsProxyDialog::GetClippingLevel() const
{
	return Tool->ProxySettings.ClippingLevel;
}

void SBuildingsProxyDialog::ClippingLevelChanged(float NewValue)
{
	Tool->ProxySettings.ClippingLevel = NewValue;
}

//Texture Resolution
void SBuildingsProxyDialog::SetTextureResolution(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo)
{
	int32 Resolution = 512;
	TTypeFromString<int32>::FromString(Resolution, **NewSelection);
	FIntPoint TextureSize(Resolution, Resolution);
	
	Tool->ProxySettings.MaterialSettings.TextureSize = TextureSize;
}

void SBuildingsProxyDialog::SetLightMapResolution( TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo )
{
	int32 Resolution = 256;
	TTypeFromString<int32>::FromString( Resolution, **NewSelection );

	Tool->ProxySettings.LightMapResolution = Resolution;
}

ECheckBoxState SBuildingsProxyDialog::GetExportNormalMap() const
{
	return Tool->ProxySettings.MaterialSettings.bNormalMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
}

void SBuildingsProxyDialog::SetExportNormalMap(ECheckBoxState NewValue)
{
	Tool->ProxySettings.MaterialSettings.bNormalMap = ( NewValue == ECheckBoxState::Checked );
}

ECheckBoxState SBuildingsProxyDialog::GetExportMetallicMap() const
{
	return Tool->ProxySettings.MaterialSettings.bMetallicMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
}

void SBuildingsProxyDialog::SetExportMetallicMap(ECheckBoxState NewValue)
{
	Tool->ProxySettings.MaterialSettings.bMetallicMap = ( NewValue == ECheckBoxState::Checked );
}

ECheckBoxState SBuildingsProxyDialog::GetExportRoughnessMap() const
{
	return Tool->ProxySettings.MaterialSettings.bRoughnessMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
}

void SBuildingsProxyDialog::SetExportRoughnessMap(ECheckBoxState NewValue)
{
	Tool->ProxySettings.MaterialSettings.bRoughnessMap = ( NewValue == ECheckBoxState::Checked );
}

ECheckBoxState SBuildingsProxyDialog::GetExportSpecularMap() const
{
	return Tool->ProxySettings.MaterialSettings.bSpecularMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
}

void SBuildingsProxyDialog::SetExportSpecularMap(ECheckBoxState NewValue)
{
	Tool->ProxySettings.MaterialSettings.bSpecularMap = ( NewValue == ECheckBoxState::Checked );
}


#undef LOCTEXT_NAMESPACE
