#pragma once

#include "CoreMinimal.h"
#include "Subsystems/WorldSubsystem.h"
#include "Engine/ObjectLibrary.h"
#include "PortaLevelSubsystem.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FStreamingLevelLoaded, const FString&, LevelName);
DECLARE_DYNAMIC_DELEGATE(FLevelLoaded);

//async function calls:
//message id in the callback that when done sends the response message
//means the header needs to indicate that it's an async call and a response is not expected immediately
//build a lambda to hold the message id

UCLASS()
class PORTAINTERFACE_API UPortaLevelSubsystem : public UWorldSubsystem
{
	GENERATED_BODY()

public:
	UPortaLevelSubsystem();

	UFUNCTION(BlueprintCallable, Category = "Porta")
	static void GetStreamingLevelsStatic(TArray<FString>& Levels);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	static void LoadStreamingLevelStatic(const FString& Name, bool UnloadCurrent, FLevelLoaded OnLoaded);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	void LoadStreamingLevel(const FString& Name, bool UnloadCurrent, FLevelLoaded OnLoaded);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	static void GetLoadedLevelsStatic(TArray<FString>& LoadedLevels);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	void GetLoadedLevels(TArray<FString>& LoadedLevels);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	void SetStreamingLevelLocation(FVector Location);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	void SetStreamingLevelRotation(FRotator Rotation);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	void SetStreamingLevelScale(FVector Scale);

	UPROPERTY(BlueprintAssignable, Category = "Porta")
	FStreamingLevelLoaded OnLevelLoaded;

	UPROPERTY()
	FLevelLoaded Test;

private:
	UFUNCTION()
	void NextLoadAction();

	void QueueUnload(const FString& Name);
	void QueueLoad(const FString& Name);

	void DoLoad(const FString& Name);
	void DoUnload(const FString& Name);

	TArray<FString> UnloadingLevels;
	TArray<FString> LoadingLevels;
	UPROPERTY()
	bool IsBusy;

	UPROPERTY(Transient)
	UObjectLibrary* LevelLibrary;

	UPROPERTY(Transient)
	TMap<FString, FLevelLoaded> LoadCallbacks;

	FString LastLoad;
};
