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

#pragma once

#include "CoreMinimal.h"

#if WITH_EDITOR
#if PLATFORM_WINDOWS
THIRD_PARTY_INCLUDES_START
#include "Windows\AllowWindowsPlatformTypes.h"
#include "Simplygon.h"
#include "Windows\HideWindowsPlatformTypes.h"
THIRD_PARTY_INCLUDES_END
#endif // PLATFORM_WINDOWS
#endif

#include "Misc/Guid.h"
#include "Materials/MaterialInterface.h"
#include "MaterialUtilities.h"
#include "StaticMeshDescription.h"
#include "ProfilingDebugging/ScopedTimers.h"

class ULODRecipe;
class FSkeletalMeshLODModel;
struct FSimplygonJobData;
class AStandInMeshActor;
class UStandinProxyContainer;
class AImpostorGeneratorHelperActor;

DECLARE_DELEGATE_TwoParams(FSimplygonProcessPostDelegate, const FGuid, TArray<UObject*>&);

/**
* SimplygonProcessCompleteDelegate - This Delegate is executed when a Simplygon async job is done
* NOTE: Only thread safe code can be executed in this delegate.
* @param JobData - Structure contianing data needed to complete job
* @param Pipeline - Source simplygon pipeline which was executed
*/
DECLARE_DELEGATE_TwoParams(FSimplygonProcessCompleteDelegate, const FSimplygonJobData&, const Simplygon::spPipeline&);
DECLARE_DELEGATE_TwoParams(FSimplygonProcessBatchCompleteDelegate, const FSimplygonJobData&, const Simplygon::spPipelineBatch&);
DECLARE_DELEGATE_TwoParams(FSimplygonProcessFailedDelegate, const FSimplygonJobData&, const FString&);
DECLARE_DELEGATE_ThreeParams(FSimplygonProcessProgressDelegate, const FSimplygonJobData&, int32/*ProgressPercentage*/, int32/*ProgressPercentageDelta*/);
/**
* SimplygonProcessPostDelegate - Post complete delegate executed on game thread using Simplygon Processor
*/
DECLARE_DELEGATE(FSimplygonProcessGameThreadDelegate);

/**
 * NavMesh Visibility Sample Points Update
*/
DECLARE_DELEGATE_OneParam(FSimplygonUpdateNavMeshVisibilitySamplesDelegate, const TArray<FVector>&);

/**
 * Simplygon Cutting Planes Update
*/
DECLARE_DELEGATE_OneParam(FSimplygonUpdateCuttingPlanesDelegate, const TArray<FPlane>&);

struct FSimplygonJobDelegates
{
	FSimplygonProcessProgressDelegate Progress{};
	FSimplygonProcessCompleteDelegate Complete{};
	FSimplygonProcessBatchCompleteDelegate BatchComplete{};
	FSimplygonProcessFailedDelegate Failed{};
};

struct FSimplygonJobData
{
	FGuid JobGuid{};
	void* UserData{};
	double Time{ 0 };

	private:
	mutable FDurationTimer JobTimer{ Time };

	public:
	FSimplygonJobData() { JobTimer.Start(); }

	double GetTime() const
	{
		JobTimer.Stop();
		return Time;
	}
};

struct FSimplygonLODRecipeJobData
{
	ULODRecipe* LODRecipe{};
	UObject* OriginalMesh{};
	// GeometryData material indices to MeshDescription material slot names
	TMap<int32, FName> MaterialIndexToSlotName{};
};

struct FSimplygonStandinJobData
{
	FString AssetName{};
	FString BasePackageName{};
	UPackage* Outer{};
	TArray<UMaterialInterface*> OriginalMaterials{};
	AStandInMeshActor* StandinMeshActor{};
	UStandinProxyContainer* Proxy;
};


struct FSimplygonImpostorJobData
{
	FString AssetName{};
	FString BasePackageName{};
	UPackage* Outer{};
	TArray<UMaterialInterface*> OriginalMaterials{};
	AImpostorGeneratorHelperActor* ImpostorGeneratorHelperActor{};
};