#pragma once

#include "CoreMinimal.h"
#include "Subsystems/EngineSubsystem.h"
#include "PortaAvaInterface.h"
#include "PortaUtils.h"
#include "PortaAvalancheSubsystem.generated.h"

//NOTE: this is basically an API wrapper on the actual Avalanche calls, run through an interface

UCLASS()
class PORTAINTERFACE_API UPortaAvalancheSubsystem : public UEngineSubsystem
{
	GENERATED_BODY()

public:
	static UPortaAvalancheSubsystem* Get() { return PortaUtils::GetEngineSubsystem<UPortaAvalancheSubsystem>(); }

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

	//This is misnamed, but not worth changing it on the web; this returns the RCP within an avalanche level
	UFUNCTION(BlueprintCallable, Category = "Porta")
	static FPortaPresetDesc OpenAssetEditorStatic(const FString& Path);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	static void StartAvalancheStatic(const FString& Path, const FString& Channel, const FString& BatchRequest);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	static void ContinueAvalancheAnimStatic(const FString& Path, const FString& Channel);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	static void ContinueAllAnimsStatic(const FString& Channel);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	static void ContinueCurrentThenStartNewStatic(const FString& Path, const FString& Channel, const FString& BatchRequest, FAvaLoadDelegate Callback);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	static void StopAvalancheStatic(const FString& Path, const FString& Channel);

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

	UFUNCTION(BlueprintCallable, Category = "Porta")
	static void SetAvalancheProfile(const FString& Profile);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	static void StartAvalancheChannel(const FString& Channel);

	UFUNCTION(BlueprintCallable, Category = "Porta")
	static FString GetTransitionLogicLayer(const FString& Path);

	static void SetPresetProp(const FString& Channel, const FString& Path, const FString& Property, const FString& Value);

	static void SetTexture(const FString& Path, const FString& Channel, const FString& Property, const FString& TexturePath);

	IPortaAvaInterface* AvaInterface;

private:
	template<typename... Args>
	static void CallInterface(void (IPortaAvaInterface::* Member)(Args...), Args... args);

	template<typename Ret, typename... Args>
	static Ret CallInterface(Ret(IPortaAvaInterface::* Member)(Args...), Args... args);
};
