// Copyright Pacificao. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameStateBase.h"
#include "AgrarianTypes.h"
#include "AgrarianGameState.generated.h"

UCLASS()
class AAgrarianGameState : public AGameStateBase
{
	GENERATED_BODY()

public:
	AAgrarianGameState();

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

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World")
	float WorldHours = 8.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|World", meta = (ClampMin = "0.1"))
	float GameHoursPerRealMinute = 0.1f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Calendar", meta = (ClampMin = "1", ClampMax = "366"))
	int32 DaysPerAgrarianYear = 366;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, ReplicatedUsing = OnRep_Weather, Category = "Agrarian|World")
	EAgrarianWeatherType Weather = EAgrarianWeatherType::Clear;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World")
	float AmbientTemperatureC = 12.0f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
	float RegionalDailyLowTemperatureC = 9.0f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
	float RegionalDailyHighTemperatureC = 18.0f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
	float RegionalObservedTemperatureC = 12.0f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature", meta = (ClampMin = "0.0", ClampMax = "1.0"))
	float ObservedTemperatureBlend = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
	bool bHasRegionalObservedTemperature = false;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
	FString RegionalWeatherSource = TEXT("deterministic_tile_curve");

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Weather")
	FAgrarianMappedWeatherInputs ActiveWeatherInputs;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Weather")
	FAgrarianWeatherDebugSnapshot ActiveWeatherDebug;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
	FName ActiveSolarTileId = TEXT("gz_us_ca_pacifica_utm10n_e544_n4160");

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
	float ActiveTileLatitude = 37.5925f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
	float ActiveTileLongitude = -122.4995f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
	FString ActiveTileTimeZoneId = TEXT("America/Los_Angeles");

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
	float ActiveTileUtcOffsetHours = -7.0f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar", meta = (ClampMin = "1", ClampMax = "366"))
	int32 ActiveDayOfYear = 172;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Calendar", meta = (ClampMin = "1"))
	int32 ActiveYear = 1;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Growing Season")
	FAgrarianGrowingSeasonProfile ActiveGrowingSeason;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
	bool bHasActiveTileSolarData = false;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
	float SunriseHourLocal = 6.0f;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
	float SunsetHourLocal = 20.0f;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
	float SolarNoonHourLocal = 13.0f;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
	float DayLengthHours = 14.0f;

	UFUNCTION(BlueprintCallable, Category = "Agrarian|World")
	bool IsNight() const;

	UFUNCTION(BlueprintCallable, Category = "Agrarian|World")
	void SetWeather(EAgrarianWeatherType NewWeather);

	UFUNCTION(BlueprintCallable, Category = "Agrarian|World|Temperature")
	void SetRegionalTemperatureProfile(float DailyLowTemperatureC, float DailyHighTemperatureC);

	UFUNCTION(BlueprintCallable, Category = "Agrarian|World|Temperature")
	void SetRegionalObservedTemperature(float ObservedTemperatureC, float BlendWeight, const FString& WeatherSource);

	UFUNCTION(BlueprintCallable, Category = "Agrarian|World|Weather")
	void ApplyMappedWeatherInputs(const FAgrarianMappedWeatherInputs& MappedInputs);

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Weather")
	FAgrarianWeatherDebugSnapshot GetWeatherDebugSnapshot() const;

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Temperature")
	float GetClearSkyTemperatureForHour(float HourOfDay) const;

	UFUNCTION(BlueprintCallable, Category = "Agrarian|World|Tile Solar")
	bool ConfigureActiveSolarTile(FName TileId, float Latitude, float Longitude, const FString& TimeZoneId, float UtcOffsetHours);

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Calendar")
	FAgrarianCalendarSnapshot GetCalendarSnapshot() const;

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Calendar")
	int32 GetAbsoluteAgrarianDay() const;

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Calendar")
	EAgrarianSeason GetSeasonForDay(int32 DayOfYear) const;

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Calendar")
	int32 GetDayOfSeason(int32 DayOfYear) const;

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Calendar")
	float ConvertAgrarianDaysToRealHours(float AgrarianDays) const;

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Calendar")
	float ConvertRealHoursToAgrarianDays(float RealHours) const;

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Calendar")
	float GetLongTaskProgress(int32 StartAbsoluteDay, float StartHourOfDay, float DurationAgrarianDays) const;

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Growing Season")
	bool IsDayInsideActiveGrowingSeason(int32 DayOfYear) const;

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Growing Season")
	int32 GetDaysRemainingInActiveGrowingSeason(int32 PlantDayOfYear) const;

	UFUNCTION(BlueprintPure, Category = "Agrarian|World|Growing Season")
	FAgrarianCropSeasonAssessment AssessCropForActiveGrowingSeason(int32 CropMaturityDays, int32 PlantDayOfYear) const;

protected:
	UFUNCTION()
	void OnRep_Weather();

	void UpdateSolarTimes();
	void UpdateAmbientTemperature();
};
