// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameStateBase.h"
#include "GameFramework/WorldSettings.h"
#include "DayNightGameStateBase.generated.h"

/**
 * 
 */
UCLASS()
class DAYNIGHT_API ADayNightGameStateBase : public AGameStateBase
{
	GENERATED_BODY()

	/** How long has the game been playing? */
	UPROPERTY(Replicated)
	int32 m_ElapsedGameMinutes;
	
	UPROPERTY(Replicated)
	bool m_bIsNight;

public:
	/** How many minutes are in a day? */
	const float MINUTESINDAY = 24 * 60;

	/** How much time has passed in game? */
	UFUNCTION(BlueprintPure, Category = "GameState")
	FORCEINLINE int32 GetElapsedGameMinutes() const { return m_ElapsedGameMinutes; }

	/** Time to add per day */
	UFUNCTION(BlueprintPure, Category = "GameState")
	FORCEINLINE float GetTimeOfDayIncrement() const { return (GetWorldSettings()->GetEffectiveTimeDilation() * m_TimeScale); }
	
	/** Is the game time night? */
	UFUNCTION(BlueprintPure, Category = "GameState")
	FORCEINLINE bool IsNight() const { return m_bIsNight; }

	/** Get how many days have passed. */
	UFUNCTION(BlueprintPure, Category = "GameState")
	FORCEINLINE int32 GetElapsedDays() const
	{
		const float ElapsedDays = m_ElapsedGameMinutes / MINUTESINDAY;
		return FMath::FloorToInt(ElapsedDays);
	}

	/** Get how many days have passed in minutes. */
	UFUNCTION(BlueprintPure, Category = "GameState")
	FORCEINLINE int32 GetElapsedFullDaysInMinutes() const { return GetElapsedDays() * MINUTESINDAY; }

	/** Get how many minutes have passed in the current day. */
	UFUNCTION(BlueprintPure, Category = "GameState")
	FORCEINLINE int32 GetElapsedMinutesCurrentDay() const { return m_ElapsedGameMinutes - GetElapsedFullDaysInMinutes(); }

	/** Get and update the m_bIsNight bool */
	bool GetAndUpdateIsNight();

	/** Get the time of day starting time. */
	UFUNCTION(BlueprintPure, Category = "GameState")
	FORCEINLINE int32 GetTimeOfDayStart() const { return m_TimeOfDayStart; }

	void IncrementElapsedGameMinutes(int32 time);

protected:

	/** 1.0f = realtime */
	UPROPERTY(EditDefaultsOnly, Category = "TimeOfDay", meta = (DisplayName = "Time Scale"))
	float m_TimeScale;

	/** Time in wallclock hours the day begins */
	UPROPERTY(EditDefaultsOnly, Category = "TimeOfDay", meta = (DisplayName = "Sunrise Time"))
	float m_SunriseTimeMark;

	/** Time in wallclock hours the night begins */
	UPROPERTY(EditDefaultsOnly, Category = "TimeOfDay", meta = (DisplayName = "Sunset Time"))
	float m_SunsetTimeMark;

	/** What time does the day start? */
	UPROPERTY(EditDefaultsOnly, Category = "TimeOfDay", meta = (DisplayName = "Time of Day Start"))
	int32 m_TimeOfDayStart;

	/** These don't really need a getter/setter. */
public:
	/** Skysphere name from the level. */
	UPROPERTY(EditDefaultsOnly, Category = "TimeOfDay", meta = (DisplayName = "Skysphere Name"))
	FString m_SkySphereName;

	/** Primary sun light name from the level. */
	UPROPERTY(EditDefaultsOnly, Category = "TimeOfDay", meta = (DisplayName = "Primary Sunlight Name"))
	FString m_PrimarySunLightName;

	/** Skylight name from the level. */
	UPROPERTY(EditDefaultsOnly, Category = "TimeOfDay", meta = (DisplayName = "Skylight Name"))
	FString m_SkyLightName;


public:

	ADayNightGameStateBase();

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

};
