// Copyright Ngonart OU. All Rights Reserved.
// UE5 Modular Game Framework — BP_PlanarCaptureActor (137)
// Placeable actor wrapping a BPC_PlanarCapture component. Owns the surface mesh,
// material dynamic instances, and the capture component. Handles overlap/proximity
// events feeding into the quality manager. Registers with the global subsystem.
//
// Blueprint children: BP_Mirror, BP_Portal, BP_Monitor, BP_HorrorMirror, BP_FakeWindow.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Capture/PlanarCaptureCommon.h"
#include "BP_PlanarCaptureActor.generated.h"

class UBPC_PlanarCapture;
class UStaticMeshComponent;
class UMaterialInstanceDynamic;
class UMaterialParameterCollection;
class UBoxComponent;

// Delegates
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlanarCaptureActorModeChanged, EPlanarCaptureMode, NewMode);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlanarCaptureSurfaceDestroyed, ABP_PlanarCaptureActor*, Surface);

/**
 * BP_PlanarCaptureActor — Placeable actor for mirrors, portals, monitors, etc.
 *
 * Blueprint children configure the mode, mesh, materials, and capture settings.
 * This actor is the designer-facing interface — all runtime logic lives in
 * BPC_PlanarCapture and SS_PlanarCaptureManager.
 *
 * Multiplayer: Spawned on all clients. Capture rendering is local-only.
 * Surface state (destroyed, on/off) may replicate via RepNotify.
 */
UCLASS(Blueprintable, BlueprintType)
class PG_FRAMEWORK_API ABP_PlanarCaptureActor : public AActor
{
	GENERATED_BODY()

public:
	ABP_PlanarCaptureActor();

	// ========================================================================
	// Components
	// ========================================================================

	/** The surface mesh — a plane, quad, or frame. */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Capture|Components")
	TObjectPtr<UStaticMeshComponent> SurfaceMesh;

	/** Proximity trigger volume for quality scoring. */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Capture|Components")
	TObjectPtr<UBoxComponent> ProximityTrigger;

	/** The core capture component. */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Capture|Components")
	TObjectPtr<UBPC_PlanarCapture> CaptureComponent;

	// ========================================================================
	// Configuration
	// ========================================================================

	/** Display name for debug and logging. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
	FString SurfaceDisplayName;

	/** Whether this surface starts enabled. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
	bool bStartEnabled = true;

	/** Whether this surface can be destroyed (shattered mirror, broken monitor). */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
	bool bDestructible = false;

	/** Material Parameter Collection for global surface parameters. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Material")
	TObjectPtr<UMaterialParameterCollection> SurfaceMPC;

	// ========================================================================
	// Runtime State
	// ========================================================================

	/** Whether this surface is currently active. */
	UPROPERTY(BlueprintReadOnly, Category = "Capture|Runtime")
	bool bIsActive = false;

	/** Dynamic material instance on the surface mesh. */
	UPROPERTY(BlueprintReadOnly, Category = "Capture|Runtime")
	TObjectPtr<UMaterialInstanceDynamic> SurfaceMaterialInstance;

	// ========================================================================
	// Public API
	// ========================================================================

	/** Enable the capture surface. */
	UFUNCTION(BlueprintCallable, Category = "Capture")
	void EnableSurface();

	/** Disable the capture surface (stops rendering, releases budget). */
	UFUNCTION(BlueprintCallable, Category = "Capture")
	void DisableSurface();

	/** Set the capture mode at runtime. */
	UFUNCTION(BlueprintCallable, Category = "Capture")
	void SetCaptureMode(EPlanarCaptureMode NewMode);

	/** Set the surface material at runtime (e.g., swap between clean/dirty mirror). */
	UFUNCTION(BlueprintCallable, Category = "Capture")
	void SetSurfaceMaterial(UMaterialInterface* NewMaterial);

	/** Set a single MPC scalar parameter for this surface. */
	UFUNCTION(BlueprintCallable, Category = "Capture|Material")
	void SetSurfaceMPCParameter(FName ParameterName, float Value);

	/** Destroy the surface (shatter mirror, break monitor). Triggers visual effect. */
	UFUNCTION(BlueprintCallable, Category = "Capture")
	void DestroySurface();

	// ========================================================================
	// Overrides
	// ========================================================================

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

	// ========================================================================
	// Event Dispatchers
	// ========================================================================

	UPROPERTY(BlueprintAssignable, Category = "Capture|Events")
	FOnPlanarCaptureActorModeChanged OnModeChanged;

	UPROPERTY(BlueprintAssignable, Category = "Capture|Events")
	FOnPlanarCaptureSurfaceDestroyed OnSurfaceDestroyed;

protected:
	// ========================================================================
	// Overlap Events (Proximity Trigger)
	// ========================================================================

	UFUNCTION()
	void OnProximityBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
		UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION()
	void OnProximityEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
		UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

	// ========================================================================
	// RepNotify (multiplayer)
	// ========================================================================

	UFUNCTION()
	void OnRep_IsActive();

	/** Replicated active state for server-authoritative surface control. */
	UPROPERTY(ReplicatedUsing = OnRep_IsActive)
	bool bRepIsActive = false;

	// ========================================================================
	// Internal
	// ========================================================================

	/** Register with the global manager subsystem. */
	void RegisterWithManager();

	/** Create the dynamic material instance from the surface mesh material. */
	void CreateMaterialInstance();
};
