#include "PortaAvalancheSubsystem.h"

template<typename... Args>
void UPortaAvalancheSubsystem::CallInterface(void (IPortaAvaInterface::* Member)(Args...), Args... args)
{
	auto Ava = Get()->AvaInterface;
	if (Ava)
	{
		(Ava->*Member)(args...);
	}
}

template<typename Ret, typename... Args>
Ret UPortaAvalancheSubsystem::CallInterface(Ret(IPortaAvaInterface::* Member)(Args...), Args... args)
{
	auto Ava = Get()->AvaInterface;
	if (Ava)
		return (Ava->*Member)(args...);

	//some trickery to get this to compile. This code should probably never run.
	PortaUtils::Initializer<Ret> ret;
	return ret.t;
}


void UPortaAvalancheSubsystem::GetAvalancheChannels(TArray<FString>& OutChannels)
{
	CallInterface<TArray<FString>& >(&IPortaAvaInterface::GetAvalancheChannels, OutChannels);
}

FPortaPresetDesc UPortaAvalancheSubsystem::OpenAssetEditorStatic(const FString& Path)
{
	return CallInterface<FPortaPresetDesc, const FString&>(&IPortaAvaInterface::GetAvalanchePreset, Path);
}

void UPortaAvalancheSubsystem::StartAvalancheStatic(const FString& Path, const FString& Channel, const FString& BatchRequest)
{
	CallInterface<const FString&, const FString&, const FString& >(&IPortaAvaInterface::StartAvalanche, Path, Channel, BatchRequest);
}

void UPortaAvalancheSubsystem::ContinueAvalancheAnimStatic(const FString& Path, const FString& Channel)
{
	CallInterface<const FString&, const FString&>(&IPortaAvaInterface::ContinueAvalancheAnim, Path, Channel);
}

void UPortaAvalancheSubsystem::ContinueAllAnimsStatic(const FString& Channel)
{
	CallInterface<const FString&>(&IPortaAvaInterface::ContinueAllAnims, Channel);
}

void UPortaAvalancheSubsystem::ContinueCurrentThenStartNewStatic(const FString& Path, const FString& Channel, const FString& BatchRequest, FAvaLoadDelegate Callback)
{
	CallInterface<const FString&, const FString&, const FString&, FAvaLoadDelegate>(&IPortaAvaInterface::ContinueCurrentThenStartNew, Path, Channel, BatchRequest, Callback);
}

void UPortaAvalancheSubsystem::StopAvalancheStatic(const FString& Path, const FString& Channel)
{
	CallInterface<const FString&, const FString&>(&IPortaAvaInterface::StopAvalanche, Path, Channel);
}

void UPortaAvalancheSubsystem::GetAvalancheProfiles(TArray<FString>& OutProfiles)
{
	CallInterface<TArray<FString>& >(&IPortaAvaInterface::GetAvalancheProfiles, OutProfiles);
}

void UPortaAvalancheSubsystem::SetAvalancheProfile(const FString& Profile)
{
	CallInterface<const FString&>(&IPortaAvaInterface::SetAvalancheProfile, Profile);
}

void UPortaAvalancheSubsystem::StartAvalancheChannel(const FString& Channel)
{
	CallInterface<const FString&>(&IPortaAvaInterface::StartAvalancheChannel, Channel);
}

FString UPortaAvalancheSubsystem::GetTransitionLogicLayer(const FString& Path)
{
	return CallInterface<FString, const FString&>(&IPortaAvaInterface::GetTransitionLogicLayer, Path);
}

void UPortaAvalancheSubsystem::SetPresetProp(const FString& Channel, const FString& Path, const FString& Property, const FString& Value)
{
	CallInterface<const FString&, const FString&, const FString&, const FString&>(&IPortaAvaInterface::SetPresetProp, Channel, Path, Property, Value);
}

void UPortaAvalancheSubsystem::SetTexture(const FString& Path, const FString& Channel, const FString& Property, const FString& TexturePath)
{
	CallInterface<const FString&, const FString&, const FString&, const FString&>(&IPortaAvaInterface::SetTexture, Path, Channel, Property, TexturePath);
}
