// Copyright Epic Games, Inc. All Rights Reserved.

#include "EndlessVendettaGameMode.h"
#include "EndlessVendettaCharacter.h"
#include "EVGameInstance.h"
#include "UObject/ConstructorHelpers.h"
#include "EndlessVendetta/AI/EnemyCharacter.h"
#include "EndlessVendetta/AI/AIControlHub.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/DamageEvents.h"
#include "Misc/Guid.h"

AEndlessVendettaGameMode::AEndlessVendettaGameMode() : Super()
{
	// set default pawn class to our Blueprinted character
	static ConstructorHelpers::FClassFinder<APawn> PlayerPawnClassFinder(TEXT("/Game/FirstPerson/Blueprints/BP_FirstPersonCharacter"));
	DefaultPawnClass = PlayerPawnClassFinder.Class;
}

void AEndlessVendettaGameMode::KillAllEnemies()
{
	TArray<AActor*> EnemyCharacters;
	UGameplayStatics::GetAllActorsOfClass(GetWorld(), AEnemyCharacter::StaticClass(), EnemyCharacters);
	for (AActor* EnemyActor : EnemyCharacters)
	{
		AEnemyCharacter* EnemyCharacter = Cast<AEnemyCharacter>(EnemyActor);
		EnemyCharacter->TakeDamage(EnemyCharacter->MaxHealth, FDamageEvent(), GetWorld()->GetFirstPlayerController(), GetWorld()->GetFirstPlayerController()->GetOwner());
	}
}

void AEndlessVendettaGameMode::SetLocalAIAlertLevel(int NewAlertLevel)
{
	TArray<AActor*> AIControlHubActors;
	UGameplayStatics::GetAllActorsOfClass(GetWorld(), AAIControlHub::StaticClass(), AIControlHubActors);
	for (AActor* AIControlHubActor : AIControlHubActors)
	{
		AAIControlHub* AIControlHub = Cast<AAIControlHub>(AIControlHubActor);
		AIControlHub->SetPlayerLastKnownLocation();
		AIControlHub->SetAlertLevel(NewAlertLevel);
	}
}

void AEndlessVendettaGameMode::SendEvent(FString EventKey, FString EventData)
{
	const FString EventID = GenerateUUID();
	const FString EventTime = FDateTime::Now().ToString();
	if (EventData.IsEmpty()) EventData = "None";
	const auto Request = FHttpModule::Get().CreateRequest();
	Request->SetURL(TelemetryURLEvents);
	Request->SetVerb("POST");
	Request->SetHeader("Content-Type", "application/json");
	Request->SetHeader("Accept", "application/json");
	Request->SetContentAsString("{\"SessionID\":\"" + SessionID + "\",\"PlayerGUID\":\"" + PlayerGUID + "\",\"EventID\":\"" + EventID + "\",\"Timestamp\":\"" + EventTime + "\",\"EventKey\":\"" + EventKey + "\",\"EventData\":\"" + EventData + "\"}");
	Request->OnProcessRequestComplete().BindLambda([EventKey, EventData](FHttpRequestPtr request, FHttpResponsePtr response, bool success)
	{
		GLog->Log("Telemetry: " + response->GetContentAsString() + "\nEvent Key: " + EventKey + " Event Data: " + EventData);
	});
	Request->ProcessRequest();
}

FString AEndlessVendettaGameMode::GenerateUUID()
{
	uint8 RandomBytes[16];
	const FDateTime Now = FDateTime::UtcNow();
	const int64 TimeStamp = Now.ToUnixTimestamp();
	FPlatformMath::RandInit(TimeStamp);

	for (int32 Index = 0; Index < 16; ++Index)
	{
		RandomBytes[Index] = FMath::Rand() % 256;
	}
	FMemory::Memswap(RandomBytes, &RandomBytes[8], 8);
	const uint32 ProcessID = FPlatformProcess::GetCurrentProcessId();
	FMemory::Memcpy(RandomBytes + 12, &ProcessID, sizeof(uint32));

	// Set version (4) and variant (RFC4122) bits
	RandomBytes[6] = (RandomBytes[6] & 0x0F) | 0x40; // version 4
	RandomBytes[8] = (RandomBytes[8] & 0x3F) | 0x80; // variant RFC4122

	FGuid UUID;
	FMemory::Memcpy(&UUID, RandomBytes, 16);
	FString UUIDString = UUID.ToString();
	UUIDString = UUIDString.Replace(TEXT("{"), TEXT(""));
	UUIDString = UUIDString.Replace(TEXT("}"), TEXT(""));
	UUIDString = UUIDString.Replace(TEXT("-"), TEXT(""));

	return UUIDString;
}

void AEndlessVendettaGameMode::BeginPlay()
{
	Super::BeginPlay();
	SessionID = Cast<UEVGameInstance>(GetGameInstance())->GlobalSessionID;
}
