// Copyright Pacificao. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "AgrarianInteractable.h"
#include "AgrarianPersistentStateProvider.h"
#include "AgrarianTypes.h"
#include "AgrarianCampfire.generated.h"

class UPointLightComponent;
class UParticleSystemComponent;
class UAgrarianPersistentActorComponent;
class UAudioComponent;
class USoundBase;
class UStaticMeshComponent;

UCLASS(Blueprintable)
class AAgrarianCampfire : public AActor, public IAgrarianInteractable, public IAgrarianPersistentStateProvider
{
	GENERATED_BODY()

public:
	AAgrarianCampfire();

	virtual void Tick(float DeltaSeconds) override;
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire")
	TObjectPtr<UStaticMeshComponent> Mesh;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Visuals")
	TObjectPtr<UStaticMeshComponent> StoneRingProxy;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Visuals")
	TObjectPtr<UStaticMeshComponent> LogProxyA;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Visuals")
	TObjectPtr<UStaticMeshComponent> LogProxyB;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Visuals")
	TObjectPtr<UStaticMeshComponent> LogProxyC;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Visuals")
	TObjectPtr<UStaticMeshComponent> EmberProxy;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire")
	TObjectPtr<UPointLightComponent> FireLight;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Effects")
	TObjectPtr<UParticleSystemComponent> SmokeEffect;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Audio")
	TObjectPtr<UAudioComponent> FireLoopAudioComponent;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Audio")
	TObjectPtr<UAudioComponent> FireEventAudioComponent;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Persistence")
	TObjectPtr<UAgrarianPersistentActorComponent> PersistentActorComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing = OnRep_FireState, Category = "Agrarian|Fire")
	bool bLit = false;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire", meta = (ClampMin = "0"))
	float FuelSeconds = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire", meta = (ClampMin = "0"))
	float WarmthRadius = 550.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire", meta = (ClampMin = "0"))
	float WarmthPerSecond = 0.02f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Cooking")
	bool bCookingPlaceholderEnabled = true;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Cooking", meta = (ClampMin = "0"))
	float CookingSecondsRequired = 30.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Cooking", meta = (ClampMin = "0"))
	float CookingProgressSeconds = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0", ClampMax = "100"))
	float FireRiskScore = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
	float LitDurationSeconds = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
	float SecondsSinceMaintenance = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Risk")
	bool bFireAreaCleared = false;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Risk")
	bool bFireContained = false;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
	float UnmaintainedRiskDelaySeconds = 120.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
	float PoorMaintenanceRiskPerSecond = 0.055f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
	float HighFuelRiskThresholdSeconds = 180.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
	float HighFuelRiskPerSecond = 0.025f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0", ClampMax = "1"))
	float ClearedAreaRiskMultiplier = 0.4f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0", ClampMax = "1"))
	float ContainedFireRiskMultiplier = 0.35f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
	float WatchedMaintenanceRiskReduction = 8.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
	float ClearedAreaRiskReduction = 24.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
	float ContainedFireRiskReduction = 28.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Vegetation", meta = (ClampMin = "0", ClampMax = "100"))
	float GrassIgnitionRiskScore = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Vegetation", meta = (ClampMin = "0", ClampMax = "100"))
	float ForestIgnitionRiskScore = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Vegetation")
	bool bGrassOrBrushIgnited = false;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Vegetation")
	bool bForestFuelIgnited = false;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Vegetation", meta = (ClampMin = "0"))
	float VegetationIgnitionCheckRadius = 700.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Vegetation", meta = (ClampMin = "0"))
	float VegetationIgnitionFuelScoreThreshold = 8.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Vegetation", meta = (ClampMin = "0"))
	float VegetationIgnitionRiskPerSecond = 0.035f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Structure", meta = (ClampMin = "0", ClampMax = "100"))
	float StructureIgnitionRiskScore = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Structure")
	bool bStructureIgnited = false;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Structure", meta = (ClampMin = "0"))
	float StructureIgnitionCheckRadius = 650.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Structure", meta = (ClampMin = "0"))
	float StructureIgnitionFuelScoreThreshold = 2.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Structure", meta = (ClampMin = "0"))
	float StructureIgnitionRiskPerSecond = 0.08f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Spread", meta = (ClampMin = "0", ClampMax = "100"))
	float GrassFireIntensity = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Spread", meta = (ClampMin = "0", ClampMax = "100"))
	float ForestFireIntensity = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Spread", meta = (ClampMin = "0", ClampMax = "100"))
	float StructureFireIntensity = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Spread", meta = (ClampMin = "0"))
	float ActiveFireSpreadRadius = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Spread", meta = (ClampMin = "0"))
	float BaseFireSpreadRadius = 250.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Spread", meta = (ClampMin = "0"))
	float MaxFireSpreadRadius = 3500.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Spread", meta = (ClampMin = "0"))
	float FireSpreadIntensityPerSecond = 0.18f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Spread", meta = (ClampMin = "0"))
	float FireSuppressionPressure = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Suppression", meta = (ClampMin = "0"))
	float WaterSuppressionStrength = 35.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Suppression", meta = (ClampMin = "0"))
	float DirtSandSuppressionStrength = 24.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Suppression", meta = (ClampMin = "0"))
	float FirebreakSuppressionStrength = 30.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Suppression", meta = (ClampMin = "0"))
	float ToolSuppressionStrength = 18.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Weather", meta = (ClampMin = "1"))
	float RainFuelDrainMultiplier = 1.5f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Weather", meta = (ClampMin = "1"))
	float StormFuelDrainMultiplier = 2.5f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Weather", meta = (ClampMin = "0"))
	float WetWeatherExtinguishFuelThresholdSeconds = 6.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Weather")
	bool bWetWeatherCanExtinguish = true;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Audio")
	TObjectPtr<USoundBase> FireLoopSound;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Audio")
	TObjectPtr<USoundBase> IgniteSound;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Audio")
	TObjectPtr<USoundBase> ExtinguishSound;

	virtual FText GetInteractionText_Implementation(const AAgrarianGameCharacter* Interactor) const override;
	virtual bool CanInteract_Implementation(const AAgrarianGameCharacter* Interactor) const override;
	virtual void Interact_Implementation(AAgrarianGameCharacter* Interactor) override;
	virtual void CapturePersistentState_Implementation(UAgrarianPersistentActorComponent* PersistentComponent) const override;
	virtual void ApplyPersistentState_Implementation(UAgrarianPersistentActorComponent* PersistentComponent) override;

	UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire")
	void AddFuel(float Seconds);

	UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire")
	void Extinguish();

	UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire|Risk")
	void MaintainFire(bool bClearArea, bool bContainFire);

	UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire|Risk")
	void WatchFire();

	UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire|Risk")
	void ClearAreaAroundFire();

	UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire|Risk")
	void ContainFire();

	UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire|Suppression")
	void ApplyFireSuppression(float SuppressionAmount, FName SuppressionSource);

	UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire|Suppression")
	void ApplyWaterSuppression();

	UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire|Suppression")
	void ApplyDirtSandSuppression();

	UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire|Suppression")
	void ApplyFirebreakSuppression();

	UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire|Suppression")
	void ApplyToolSuppression();

	UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Agrarian|Fire|Risk")
	float GetFireRiskRatio() const;

	UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Agrarian|Fire|Cooking")
	bool CanCook() const;

	UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Agrarian|Fire|Cooking")
	float GetCookingProgressRatio() const;

	UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Agrarian|Fire|Weather")
	float GetWeatherFuelDrainMultiplier() const;

	UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Agrarian|Fire|Weather")
	bool IsWetWeatherActive() const;

protected:
	UFUNCTION()
	void OnRep_FireState();

	UFUNCTION(NetMulticast, Unreliable)
	void MulticastPlayFireEventSound(bool bIgnited);

	EAgrarianWeatherType GetCurrentWeather() const;
	void SetLit(bool bNewLit);
	void UpdateVisualState();
	void WarmNearbyCharacters(float DeltaSeconds);
	void UpdateFireRisk(float DeltaSeconds);
	float GetFireRiskGrowthPerSecond() const;
	void UpdateVegetationIgnitionRisk(float DeltaSeconds);
	float GetVegetationFuelScoreNearFire(float& OutGrassFuelScore, float& OutForestFuelScore) const;
	float GetVegetationIgnitionWeatherMultiplier() const;
	void UpdateStructureIgnitionRisk(float DeltaSeconds);
	float GetStructureFuelScoreNearFire() const;
	void UpdateServerAuthoritativeFireSpread(float DeltaSeconds);
	float GetFireSpreadWeatherMultiplier() const;
	float GetActiveBurningFuelScore() const;
	void ReduceFireRisks(float Amount);
	void ReduceActiveFireIntensity(float Amount);
};
