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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "LuprexSockets.h"
#include "BreakToDebugger.h"
#include "LuprexGameModeBase.generated.h"

/**
 *
 */
UCLASS(BlueprintType)
class INTEGRATION_API ALuprexGameModeBase : public AGameModeBase
{
	GENERATED_BODY()
	
public:
	ALuprexGameModeBase();
	~ALuprexGameModeBase();
	virtual void BeginPlay() override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason);

	// Delete all the state created in BeginPlay.  That
	// includes: the Luprex engine, the thread, and the socket state.
	void ResetToInitialState();

	// Initialize the Luprex DLL, and do other global initialization.
	void InitializeGlobalState();
	
	// Send prints into Unreal, for display on the virtual console.
	UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Miscellaneous")
	void ConsoleAddOutput(const FString& text);

	UFUNCTION(BlueprintCallable, Category = "Luprex|Miscellaneous")
	int64 GetPlayerId();

	// Transfer console output from the Luprex engine to unreal.
	void UpdateConsoleOutput();

	// Update the tangibles according to what Luprex tells us.
	// This also includes calling 'AnimationQueueChanged' on all
	// tangibles that have been changed.
	void UpdateTangibles();

	// Look for a tangible whose ID is equal to the current actor ID.
	// Tell the player controller to possess that tangible.
	void UpdatePossessedTangible();

	// If the engine wants a new copy of the lua source code,
	// provide it.
	void UpdateLuaSourceCode();

	// Update Sockets and Lua.  Feeds socket data into the luprex engine,
	// and also calls play_update, the main Lua update function that causes
	// Luprex to execute the majority of all the Lua code that needs processing.
	void UpdateSocketsAndLua();

	// Post-tick function.
	void OnWorldPostActorTick(UWorld* InWorld, ELevelTick InLevelTick, float InDeltaSeconds);

	// Get the current Luprex Game Mode Base, given a Context object.
	static ALuprexGameModeBase *FromContext(const UObject *Context);

	// Set the ReloadSource flag on the current Luprex game mode, causing
	// the Lua source to be reloaded on the next tick.
	UFUNCTION(BlueprintCallable, Category = "Luprex|Miscellaneous", meta = (WorldContext = "WorldContextObject"))
	static void TriggerReloadSource(const UObject *WorldContextObject);
	
	// Luprex socket system.
	TUniquePtr<FlxSockets> Sockets;

	// True if 'BeginPlay' has been successfully completed.
	bool Playing = false;

	// This is always true unless you use the debugger to set it to false.
	bool TickEnabled = true;

	// True to trigger a source reload.
	bool ReloadSource = false;

	// Current Player ID
	int64 PlayerId = 0;

	// Amount of elapsed time since BeginPlay.
	float EngineSeconds = 0.0f;

	// This allows us to post-tick.
	FDelegateHandle OnWorldPostActorTickHandle;

	// The device that implements BreakToDebuggerLogVerbosity, above.
	TUniquePtr<FlxBreakToDebuggerOutputDevice> BreakToDebuggerLogVerbosityDevice;
};
