// Fill out your copyright notice in the Description page of Project Settings.


#include "ServerAutoStart.h"
#include "PortaSettings.h"
#include "Engine/Engine.h"
#include "Misc/Paths.h"

static const FString powerShell(TEXT("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"));

// Called when the game starts or when spawned
void UServerAutoStart::Initialize(FSubsystemCollectionBase& Collection)
{
	FString PreviewPluginPath = FPaths::ProjectPluginsDir() + "PortaPreview/";
	if (!FPaths::DirectoryExists(PreviewPluginPath))
	{
		PreviewPluginPath = FPaths::ProjectPluginsDir() + "PortaInterface/PortaPreview/";
	}

	BatScript = PreviewPluginPath + "Resources/run_powershell.bat";
	BatScript = FPaths::ConvertRelativePathToFull(BatScript);
	FPaths::MakePlatformFilename(BatScript);
	ScriptFolder = PreviewPluginPath + "Resources/SignallingWebServer/platform_scripts/cmd/";
	ScriptFolder = FPaths::ConvertRelativePathToFull(ScriptFolder);
	FPaths::MakePlatformFilename(ScriptFolder);

	auto Config = GetMutableDefault<UPortaSettings>();
	if (Config->ShouldStartPixelStream())
	{
		StartSignallingServer();
		StartTURNServer();
	}
}

void UServerAutoStart::Deinitialize()
{
	auto Config = GetMutableDefault<UPortaSettings>();
	if (Config->ShouldStartPixelStream())
	{
		CloseSignallingServer();
		CloseTURNServer();
	}
}

void UServerAutoStart::StartSignallingServer()
{
	if (FPlatformProcess::IsProcRunning(SignallingProcHandle) || IsSignallingServerRunning())
	{
		UE_LOG(LogTemp, Warning, TEXT("Pixel Streaming Signalling Server already running"));
		return;
	}
	auto Config = GetMutableDefault<UPortaSettings>();
	FString Arg = FString::Printf(TEXT("--HttpPort %d"), Config->PixelStreamServerHttpPort);

	SignallingProcHandle = StartPowershellProcess("Start_SignallingServer.ps1", Arg);
}

void UServerAutoStart::StartTURNServer()
{
	if (FPlatformProcess::IsProcRunning(TURNProcHandle) || IsTURNServerRunning())
	{
		UE_LOG(LogTemp, Warning, TEXT("Pixel Streaming TURN Server already running"));
		return;
	}

	TURNProcHandle = StartPowershellProcess("Start_TURNServer.ps1", FString());
}

void UServerAutoStart::CloseSignallingServer()
{
	if (FPlatformProcess::IsProcRunning(SignallingProcHandle))
		FPlatformProcess::TerminateProc(SignallingProcHandle, true);
}

void UServerAutoStart::CloseTURNServer()
{
	if (FPlatformProcess::IsProcRunning(TURNProcHandle))
		FPlatformProcess::TerminateProc(TURNProcHandle, true);
}

bool UServerAutoStart::IsSignallingServerRunning() const
{
	//we are assuming if someone is using the node that is installed in the scripts folder, it's the signalling server
	FString Process = ScriptFolder + "node\\node.exe";
	return IsProcessRunning(Process);
}

bool UServerAutoStart::IsTURNServerRunning() const
{
	FString Process = ScriptFolder + "coturn\\turnserver.exe";
	return IsProcessRunning(Process);
}

FProcHandle UServerAutoStart::StartPowershellProcess(const FString& File, const FString& AdditionalArg) const
{
	TArray<FString> CommandlineArgs = TArray<FString>();
	CommandlineArgs.Add("-ExecutionPolicy Bypass");
	CommandlineArgs.Add("-File \"" + ScriptFolder + File + "\"");
	if (!AdditionalArg.IsEmpty())
		CommandlineArgs.Add(AdditionalArg);

	FString Args = "";
	Args = CommandlineArgs[0];
	for (int32 v = 1; v < CommandlineArgs.Num(); v++)
	{
		Args += " " + CommandlineArgs[v];
	}

	return FPlatformProcess::CreateProc(*BatScript, *Args, false, true, false, 0, 0, nullptr, nullptr);

}

bool UServerAutoStart::IsProcessRunning(const FString& Process)
{
	FPlatformProcess::FProcEnumerator ProcIter;
	while (ProcIter.MoveNext())
	{
		FPlatformProcess::FProcEnumInfo ProcInfo = ProcIter.GetCurrent();
		FString Candidate = ProcInfo.GetFullPath();
		if (Candidate == Process)
			return true;
	}

	return false;
}
