#pragma once

#include "CoreMinimal.h"
#include "Common.h"
#include "Engine/HitResult.h"
#include "GameFramework/PlayerController.h"
#include "UObject/ObjectKey.h"
#include "PlayerControllerBase.generated.h"

class UlxRootCanvasPanel;
class UWidget;

UCLASS(BlueprintType, Blueprintable)
class INTEGRATION_API AlxPlayerControllerBase : public APlayerController
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
	static void SetLookAt(const UObject *Context, const FHitResult &HitResult);

	UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
	static const FHitResult &GetLookAt(const UObject *Context);

	UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
	static const AActor *GetLookAtActor(const UObject *Context);

	UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
	static FVector2D GetLookAtPixel(const UObject *Context);

	UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
	static void SetLookAtChanged(const UObject *Context);

	// Blueprint events
	UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Look-At Detection")
	void CalculateLookAt();

	UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Look-At Detection")
	void LookAtChanged();

	// Called by GameMode each tick.
	void UpdateLookAt();

	// Called by GameMode each tick. GCs dead requests and will
	// eventually reconcile focus, pointer, and capture state.
	void UpdateInputMode();

	virtual void BeginPlay() override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

public:

	virtual void BuildInputStack(TArray<UInputComponent*>& InputStack) override;

	// Read UUserWidget::InputComponent via reflection. The field is
	// protected and has no public accessor; this reaches through the
	// FProperty so we always see the current value without caching it.
	static class UInputComponent* GetWidgetInputComponent(class UUserWidget *Widget);

	// Add a widget to the root canvas at ZOrder 0 with default slot flags.
	UFUNCTION(BlueprintCallable, Category = "Luprex|Root Canvas",
		meta = (DefaultToSelf = "Widget", HideSelfPin = "true"))
	static void AddWidgetToRoot(class UUserWidget *Widget);

	// Get the player controller, cast to AlxPlayerControllerBase.
	static AlxPlayerControllerBase *FromContext(const UObject *Context);

	UPROPERTY()
	FHitResult CurrentLookAt;

	// The single top-level UUserWidget added to the viewport. All
	// top-level UI widgets are children of RootCanvas inside it.
	UPROPERTY()
	UUserWidget *RootWidget = nullptr;

	// The root canvas panel inside RootWidget. Children of this
	// canvas are the top-level widgets; their slots carry both
	// layout and input-mode configuration.
	UPROPERTY()
	UlxRootCanvasPanel *RootCanvas = nullptr;

	bool MustCallLookAtChanged = false;
};
