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

#pragma once

#include "Runtime/Online/HTTP/Public/Http.h"
#include "CoreMinimal.h"
#include "Engine.h"
#include "GameFramework/Actor.h"
#include "BP_InnoactivePortalAccessControlHandler.generated.h"



// calls the authentication function from a separate thread
class AuthThreadHandler : public FRunnable
{
public:
	FRunnableThread* Thread;

	// Thread handling
	AuthThreadHandler(ABP_InnoactivePortalAccessControlHandler* authHandler, FString clientId) :authHandler(authHandler), clientId(clientId)
	{
		Thread = FRunnableThread::Create(this, TEXT("AuthThreadHandler"), 0, TPri_BelowNormal); //windows default = 8mb for thread, could specify
	};



	virtual ~AuthThreadHandler();

	virtual uint32 Run();

	ABP_InnoactivePortalAccessControlHandler* authHandler;
	FString filePath;
	FString clientId;
};

UCLASS()
class ABP_InnoactivePortalAccessControlHandler : public AActor
{
	GENERATED_BODY()

public:
	// Public flag that determines whether to show logs on screen or not
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Innoactive Portal Access Control")
		bool showLogs = false;

	// Public flag that defines if a second thread is used to authorize the user
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Innoactive Portal Access Control")
		bool useMultithreading = true;

	// Unloads any library used in the auth process, should be called after the process is finished or before destroying the blueprint
	UFUNCTION(BlueprintCallable, Category = "Innoactive Portal Access Control")
		void ReleaseResources();

	// Main auth function, handling the process of authorizing the user
	// Uses the OnAuthSuccessful and OnAuthFailed callback to return the result
	UFUNCTION(BlueprintCallable, Category = "Innoactive Portal Access Control")
		void StartAuthorization(FString clientId);

	// Informs about the current progress of the auth process. This function can be used in UI widgets to display information to the user
	UFUNCTION(BlueprintCallable, Category = "Innoactive Portal Access Control")
		FString GetCurrentLogMessage();

	// Called when the user authenticated successfully
	UFUNCTION(BlueprintImplementableEvent, Category = "Innoactive Portal Access Control")
		void OnAuthorizationSuccessful();

	// Called when the user failed to authenticate
	UFUNCTION(BlueprintImplementableEvent, Category = "Innoactive Portal Access Control")
		void OnAuthorizationFailed(const FString& error);

	// Sets default values for this actor's properties
	ABP_InnoactivePortalAccessControlHandler();
	FString* currentLogMessage;
	FString logsPath;
	FString quitFilePath;
	// Logs information to the screen or UELogs based on the showLogs flag
	void DebugLog(FString info);
	// Prints the information to the logs and calls OnAuthorizationSuccessful
	void Success(FString info);
	// Prints the information to the logs and calls OnAuthorizationFailed
	void Fail(FString info);
	// Attempts to authorize through the portal desktop client
	void Authorize(FString clientId);

private:
	/// Class instance calling the auth function in a separate thread
	AuthThreadHandler* authThreadHandler;
	/// Checks both of the Access Control Library files against known hash values to prevent mock implementations
	bool CheckAccessControlLibrariesIntegrity();
	/// Compares the SHA256 value of the given file and the expected hash
	bool CheckLibraryIntegrity(FString filePath, FString expectedHash);
	/// Calculates the SHA256 hash value of the file at the given path
	FString GetSHA256Hash(FString filePath);
	/// Get the path to the given dll
	FString GetLibraryPath(FString fileName);
	/// Logs the plugin version
	void LogPluginVersion();
};
