// Copyright Ngonart OU. All Rights Reserved.
// UE5 Modular Game Framework — PlanarCaptureCommon
// Shared enums, structs, and quality profile definitions for the Planar Capture System.
// Used by BPC_PlanarCapture, BP_PlanarCaptureActor, and SS_PlanarCaptureManager.

#pragma once

#include "CoreMinimal.h"
#include "Engine/TextureRenderTarget2D.h"
#include "PlanarCaptureCommon.generated.h"

// ============================================================================
// Enums
// ============================================================================

/**
 * The mode of the capture surface — determines camera math, rendering behavior,
 * and material configuration.
 */
UENUM(BlueprintType)
enum class EPlanarCaptureMode : uint8
{
	Mirror         UMETA(DisplayName = "Mirror"),
	Portal         UMETA(DisplayName = "Portal"),
	Monitor        UMETA(DisplayName = "Monitor / Security Screen"),
	HorrorMirror   UMETA(DisplayName = "Horror Mirror"),
	HorrorPortal   UMETA(DisplayName = "Horror Portal"),
	FakeWindow     UMETA(DisplayName = "Fake Window"),
};

/**
 * Quality tier for a capture surface. Managed globally by SS_PlanarCaptureManager.
 */
UENUM(BlueprintType)
enum class EPlanarCaptureQualityTier : uint8
{
	Off     UMETA(DisplayName = "Off — No capture"),
	Low     UMETA(DisplayName = "Low — 256px, 4fps"),
	Medium  UMETA(DisplayName = "Medium — 512px, 15fps"),
	High    UMETA(DisplayName = "High — 1024px, 30fps"),
	Hero    UMETA(DisplayName = "Hero — 2048px, 60fps"),
};

/**
 * Result codes for capture surface initialization.
 */
UENUM(BlueprintType)
enum class EPlanarCaptureInitResult : uint8
{
	Success              UMETA(DisplayName = "Success"),
	NoRenderTargetPool   UMETA(DisplayName = "Failed — No Render Target in Pool"),
	InvalidSurfaceMesh   UMETA(DisplayName = "Failed — Invalid Surface Mesh"),
	BudgetExceeded       UMETA(DisplayName = "Failed — Budget Exceeded"),
	ManagerUnavailable   UMETA(DisplayName = "Failed — Manager Unavailable"),
};

// ============================================================================
// Structs
// ============================================================================

/**
 * Quality profile — defines render target resolution, capture interval,
 * and per-feature toggles for a single quality tier.
 */
USTRUCT(BlueprintType)
struct PG_FRAMEWORK_API FPlanarCaptureQualityProfile
{
	GENERATED_BODY()

	/** Render target resolution (square: 256, 512, 1024, 2048). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Quality")
	int32 RenderTargetSize = 512;

	/** Minimum interval between captures in seconds (1.0 / FPS). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Quality")
	float CaptureInterval = 0.0667f; // ~15fps

	/** Shadow rendering mode for the capture. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
	bool bEnableShadows = true;

	/** Allow post-process effects in the capture. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
	bool bEnablePostProcess = false;

	/** Allow exponential height fog in the capture. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
	bool bEnableFog = false;

	/** Allow bloom in the capture. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
	bool bEnableBloom = false;

	/** Allow ambient occlusion in the capture. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
	bool bEnableAO = false;

	/** Allow Lumen global illumination in the capture (expensive). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
	bool bEnableLumen = false;

	/** Allow motion blur in the capture. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
	bool bEnableMotionBlur = false;

	/** Enable oblique near-clip plane (required for portals flush with geometry). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
	bool bEnableClipPlane = true;

	/** Number of frames to delay the reflection (0 = off, N = horror lag effect). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Horror", meta = (ClampMin = "0", ClampMax = "30"))
	int32 DelayedFrameCount = 0;
};

/**
 * Single entry in a capture surface's ShowOnly or Hidden actor list.
 */
USTRUCT(BlueprintType)
struct PG_FRAMEWORK_API FPlanarCaptureActorListEntry
{
	GENERATED_BODY()

	/** The actor to show exclusively or hide. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|ActorList")
	TSoftObjectPtr<AActor> Actor;

	/** Whether this actor is currently active in the list. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|ActorList")
	bool bActive = true;
};

/**
 * Scoring data for a capture surface — computed each frame by the manager
 * to determine quality tier assignment.
 */
USTRUCT(BlueprintType)
struct PG_FRAMEWORK_API FPlanarCaptureScore
{
	GENERATED_BODY()

	/** Distance from viewer to surface in world units. */
	UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
	float DistanceToViewer = FLT_MAX;

	/** Screen coverage percentage (0.0 to 1.0). */
	UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
	float ScreenCoverage = 0.0f;

	/** Dot product of viewer forward and surface normal (1.0 = facing, 0.0 = edge-on). */
	UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
	float FacingAngle = 0.0f;

	/** Whether the surface is within the viewer's frustum. */
	UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
	bool bInFrustum = false;

	/** Scripted priority override (0.0 to 1.0, from gameplay systems). */
	UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
	float ScriptedPriority = 0.0f;

	/** Composite score (0.0 to 1.0) — higher = more important. */
	UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
	float CompositeScore = 0.0f;
};

/**
 * Render target pool entry — managed by SS_PlanarCaptureManager.
 */
USTRUCT()
struct PG_FRAMEWORK_API FPlanarCaptureRenderTargetEntry
{
	GENERATED_BODY()

	/** The allocated render target. */
	UPROPERTY()
	TObjectPtr<UTextureRenderTarget2D> RenderTarget = nullptr;

	/** Current size of the render target. */
	UPROPERTY()
	int32 CurrentSize = 0;

	/** Whether this entry is currently assigned to a surface. */
	UPROPERTY()
	bool bInUse = false;

	/** Which surface currently owns this entry. */
	UPROPERTY()
	TWeakObjectPtr<class ABP_PlanarCaptureActor> OwningSurface;
};
