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


#include "SettingsGraphicsWidget.h"

#include "SettingRowWidget.h"
#include "SurvivalUserSettings.h"

#define LOCTEXT_NAMESPACE "Reglages"

namespace SettingsGraphicsTab
{
	/**
	 * Index de "Personnalise" dans la ligne de qualite globale.
	 *
	 * Le moteur renvoie -1 quand les curseurs ne correspondent a aucun preset.
	 * On l'affiche comme un cinquieme choix, mais SetMaxSelectableIndex(3)
	 * empeche le joueur de le selectionner : c'est un etat dans lequel on tombe,
	 * pas un reglage qu'on choisit.
	 */
	constexpr int32 CustomQualityIndex = 4;

	/** Bas / Moyen / Eleve / Epique. Le moteur accepte aussi 4 (cinematique), qu'on n'expose pas. */
	constexpr int32 MaxQualityLevel = 3;
}

void USettingsGraphicsWidget::SetupQualityRow(USettingRowWidget* Row, const FText& Label)
{
	if (!Row)
	{
		return;
	}

	Row->SetupAsChoice(Label,
		{ LOCTEXT("QualiteBas", "Bas"),
		  LOCTEXT("QualiteMoyen", "Moyen"),
		  LOCTEXT("QualiteEleve", "Élevé"),
		  LOCTEXT("QualiteEpique", "Épique") }, 0);
}

void USettingsGraphicsWidget::NativeConstruct()
{
	Super::NativeConstruct();

	if (OverallQualityRow)
	{
		OverallQualityRow->SetupAsChoice(LOCTEXT("QualiteGlobale", "Qualité globale"),
			{ LOCTEXT("QualiteBas", "Bas"),
			  LOCTEXT("QualiteMoyen", "Moyen"),
			  LOCTEXT("QualiteEleve", "Élevé"),
			  LOCTEXT("QualiteEpique", "Épique"),
			  LOCTEXT("QualitePerso", "Personnalisé") }, 0);

		OverallQualityRow->SetMaxSelectableIndex(SettingsGraphicsTab::MaxQualityLevel);
		OverallQualityRow->OnIndexChanged.AddDynamic(this, &USettingsGraphicsWidget::HandleOverallQualityChanged);
	}

	SetupQualityRow(ViewDistanceRow, LOCTEXT("DistanceAffichage", "Distance d'affichage"));
	SetupQualityRow(FoliageRow, LOCTEXT("Vegetation", "Végétation"));
	SetupQualityRow(ShadowRow, LOCTEXT("Ombres", "Ombres"));
	SetupQualityRow(TextureRow, LOCTEXT("Textures", "Textures"));
	SetupQualityRow(VisualEffectRow, LOCTEXT("Effets", "Effets"));
	SetupQualityRow(PostProcessRow, LOCTEXT("PostProcess", "Post-process"));
	SetupQualityRow(AntiAliasingRow, LOCTEXT("AntiAliasing", "Anti-aliasing"));
	SetupQualityRow(ReflectionRow, LOCTEXT("Reflexions", "Réflexions"));
	SetupQualityRow(GlobalIlluminationRow, LOCTEXT("EclairageGlobal", "Éclairage global"));
	SetupQualityRow(ShadingRow, LOCTEXT("Ombrage", "Ombrage"));

	if (ViewDistanceRow) { ViewDistanceRow->OnIndexChanged.AddDynamic(this, &USettingsGraphicsWidget::HandleViewDistanceChanged); }
	if (FoliageRow) { FoliageRow->OnIndexChanged.AddDynamic(this, &USettingsGraphicsWidget::HandleFoliageChanged); }
	if (ShadowRow) { ShadowRow->OnIndexChanged.AddDynamic(this, &USettingsGraphicsWidget::HandleShadowChanged); }
	if (TextureRow) { TextureRow->OnIndexChanged.AddDynamic(this, &USettingsGraphicsWidget::HandleTextureChanged); }
	if (VisualEffectRow) { VisualEffectRow->OnIndexChanged.AddDynamic(this, &USettingsGraphicsWidget::HandleVisualEffectChanged); }
	if (PostProcessRow) { PostProcessRow->OnIndexChanged.AddDynamic(this, &USettingsGraphicsWidget::HandlePostProcessChanged); }
	if (AntiAliasingRow) { AntiAliasingRow->OnIndexChanged.AddDynamic(this, &USettingsGraphicsWidget::HandleAntiAliasingChanged); }
	if (ReflectionRow) { ReflectionRow->OnIndexChanged.AddDynamic(this, &USettingsGraphicsWidget::HandleReflectionChanged); }
	if (GlobalIlluminationRow) { GlobalIlluminationRow->OnIndexChanged.AddDynamic(this, &USettingsGraphicsWidget::HandleGlobalIlluminationChanged); }
	if (ShadingRow) { ShadingRow->OnIndexChanged.AddDynamic(this, &USettingsGraphicsWidget::HandleShadingChanged); }

	RefreshFromSettings();
}

void USettingsGraphicsWidget::RefreshFromSettings()
{
	USurvivalUserSettings* Settings = USurvivalUserSettings::Get();
	if (!Settings)
	{
		return;
	}

	if (OverallQualityRow)
	{
		// -1 quand les curseurs ne collent a aucun preset : c'est la que
		// "Personnalise" s'affiche.
		const int32 Overall = Settings->GetOverallScalabilityLevel();
		OverallQualityRow->SetIndexSilently(Overall >= 0 ? Overall : SettingsGraphicsTab::CustomQualityIndex);
	}

	if (ViewDistanceRow) { ViewDistanceRow->SetIndexSilently(Settings->GetViewDistanceQuality()); }
	if (FoliageRow) { FoliageRow->SetIndexSilently(Settings->GetFoliageQuality()); }
	if (ShadowRow) { ShadowRow->SetIndexSilently(Settings->GetShadowQuality()); }
	if (TextureRow) { TextureRow->SetIndexSilently(Settings->GetTextureQuality()); }
	if (VisualEffectRow) { VisualEffectRow->SetIndexSilently(Settings->GetVisualEffectQuality()); }
	if (PostProcessRow) { PostProcessRow->SetIndexSilently(Settings->GetPostProcessingQuality()); }
	if (AntiAliasingRow) { AntiAliasingRow->SetIndexSilently(Settings->GetAntiAliasingQuality()); }
	if (ReflectionRow) { ReflectionRow->SetIndexSilently(Settings->GetReflectionQuality()); }
	if (GlobalIlluminationRow) { GlobalIlluminationRow->SetIndexSilently(Settings->GetGlobalIlluminationQuality()); }
	if (ShadingRow) { ShadingRow->SetIndexSilently(Settings->GetShadingQuality()); }
}

void USettingsGraphicsWidget::ResetToDefaults()
{
	USurvivalUserSettings* Settings = USurvivalUserSettings::Get();
	if (!Settings)
	{
		return;
	}

	// "Eleve" plutot que le benchmark automatique : sur une machine modeste,
	// RunHardwareBenchmark peut descendre tres bas et le joueur ne comprendrait
	// pas pourquoi "Reinitialiser" a degrade son jeu.
	Settings->SetOverallScalabilityLevel(2);
	Settings->ApplyNonResolutionSettings();

	RefreshFromSettings();
}

void USettingsGraphicsWidget::ApplyAndRefreshOverall()
{
	USurvivalUserSettings* Settings = USurvivalUserSettings::Get();
	if (!Settings || !OverallQualityRow)
	{
		return;
	}

	Settings->ApplyNonResolutionSettings();

	// Toucher un curseur individuel fait presque toujours basculer la qualite
	// globale sur "Personnalise" : la ligne du haut doit suivre immediatement,
	// sinon elle affiche un preset qui ne correspond plus a rien.
	const int32 Overall = Settings->GetOverallScalabilityLevel();
	OverallQualityRow->SetIndexSilently(Overall >= 0 ? Overall : SettingsGraphicsTab::CustomQualityIndex);
}

void USettingsGraphicsWidget::HandleOverallQualityChanged(int32 NewIndex)
{
	USurvivalUserSettings* Settings = USurvivalUserSettings::Get();
	if (!Settings)
	{
		return;
	}

	Settings->SetOverallScalabilityLevel(FMath::Clamp(NewIndex, 0, SettingsGraphicsTab::MaxQualityLevel));
	Settings->ApplyNonResolutionSettings();

	// Un preset repositionne les dix autres lignes d'un coup.
	RefreshFromSettings();
}

void USettingsGraphicsWidget::HandleViewDistanceChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetViewDistanceQuality(NewIndex);
		ApplyAndRefreshOverall();
	}
}

void USettingsGraphicsWidget::HandleFoliageChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetFoliageQuality(NewIndex);
		ApplyAndRefreshOverall();
	}
}

void USettingsGraphicsWidget::HandleShadowChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetShadowQuality(NewIndex);
		ApplyAndRefreshOverall();
	}
}

void USettingsGraphicsWidget::HandleTextureChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetTextureQuality(NewIndex);
		ApplyAndRefreshOverall();
	}
}

void USettingsGraphicsWidget::HandleVisualEffectChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetVisualEffectQuality(NewIndex);
		ApplyAndRefreshOverall();
	}
}

void USettingsGraphicsWidget::HandlePostProcessChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetPostProcessingQuality(NewIndex);
		ApplyAndRefreshOverall();
	}
}

void USettingsGraphicsWidget::HandleAntiAliasingChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetAntiAliasingQuality(NewIndex);
		ApplyAndRefreshOverall();
	}
}

void USettingsGraphicsWidget::HandleReflectionChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetReflectionQuality(NewIndex);
		ApplyAndRefreshOverall();
	}
}

void USettingsGraphicsWidget::HandleGlobalIlluminationChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetGlobalIlluminationQuality(NewIndex);
		ApplyAndRefreshOverall();
	}
}

void USettingsGraphicsWidget::HandleShadingChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetShadingQuality(NewIndex);
		ApplyAndRefreshOverall();
	}
}

#undef LOCTEXT_NAMESPACE
