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


#include "SettingsGameplayWidget.h"

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

#define LOCTEXT_NAMESPACE "Reglages"

namespace
{
	/** Les deux seules listes de choix de cet onglet. */
	TArray<FText> MakeNoYesLabels()
	{
		return { LOCTEXT("Non", "Non"), LOCTEXT("Oui", "Oui") };
	}

	TArray<FText> MakeHoldToggleLabels()
	{
		return { LOCTEXT("Maintien", "Maintien"), LOCTEXT("Bascule", "Bascule") };
	}
}

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

	// Les libelles et les bornes sont poses une seule fois ; seules les valeurs
	// bougent ensuite, via RefreshFromSettings.
	using namespace SurvivalSettingsRange;

	if (SensitivityRow)
	{
		SensitivityRow->SetupAsNumber(LOCTEXT("Sensibilite", "Sensibilité"),
			SensitivityMin, SensitivityMax, SensitivityStep, SensitivityArrowStep, SensitivityMin, FText::GetEmpty());
		SensitivityRow->OnIndexChanged.AddDynamic(this, &USettingsGameplayWidget::HandleSensitivityChanged);
	}

	if (SeparateVerticalRow)
	{
		SeparateVerticalRow->SetupAsChoice(LOCTEXT("SensibiliteSeparee", "Sensibilité verticale séparée"),
			MakeNoYesLabels(), 0);
		SeparateVerticalRow->OnIndexChanged.AddDynamic(this, &USettingsGameplayWidget::HandleSeparateVerticalChanged);
	}

	if (SensitivityVerticalRow)
	{
		SensitivityVerticalRow->SetupAsNumber(LOCTEXT("SensibiliteVerticale", "Sensibilité verticale"),
			SensitivityMin, SensitivityMax, SensitivityStep, SensitivityArrowStep, SensitivityMin, FText::GetEmpty());
		SensitivityVerticalRow->OnIndexChanged.AddDynamic(this, &USettingsGameplayWidget::HandleSensitivityVerticalChanged);
	}

	if (InvertLookRow)
	{
		InvertLookRow->SetupAsChoice(LOCTEXT("InverserY", "Inverser l'axe vertical"), MakeNoYesLabels(), 0);
		InvertLookRow->OnIndexChanged.AddDynamic(this, &USettingsGameplayWidget::HandleInvertLookChanged);
	}

	if (FieldOfViewRow)
	{
		FieldOfViewRow->SetupAsNumber(LOCTEXT("ChampDeVision", "Champ de vision"),
			FieldOfViewMin, FieldOfViewMax, FieldOfViewStep, FieldOfViewArrowStep, FieldOfViewMin, LOCTEXT("Degres", "°"));
		FieldOfViewRow->OnIndexChanged.AddDynamic(this, &USettingsGameplayWidget::HandleFieldOfViewChanged);
	}

	if (CameraShakeRow)
	{
		CameraShakeRow->SetupAsNumber(LOCTEXT("BougeCamera", "Bougé de caméra"),
			CameraShakeMin, CameraShakeMax, CameraShakeStep, CameraShakeArrowStep, CameraShakeMin, LOCTEXT("Pourcent", " %"));
		CameraShakeRow->OnIndexChanged.AddDynamic(this, &USettingsGameplayWidget::HandleCameraShakeChanged);
	}

	if (SprintModeRow)
	{
		SprintModeRow->SetupAsChoice(LOCTEXT("Sprint", "Sprint"), MakeHoldToggleLabels(), 0);
		SprintModeRow->OnIndexChanged.AddDynamic(this, &USettingsGameplayWidget::HandleSprintModeChanged);
	}

	if (CrouchModeRow)
	{
		CrouchModeRow->SetupAsChoice(LOCTEXT("Accroupi", "Accroupi"), MakeHoldToggleLabels(), 0);
		CrouchModeRow->OnIndexChanged.AddDynamic(this, &USettingsGameplayWidget::HandleCrouchModeChanged);
	}

	RefreshFromSettings();
}

void USettingsGameplayWidget::RefreshFromSettings()
{
	USurvivalUserSettings* Settings = USurvivalUserSettings::Get();
	if (!Settings)
	{
		UE_LOG(LogTemp, Error, TEXT("USettingsGameplayWidget : GameUserSettingsClassName n'est pas configure dans DefaultEngine.ini, l'onglet restera inerte."));
		return;
	}

	// SetNumericValueSilently et non un setter classique : diffuser ici ferait
	// boucler l'onglet sur lui-meme.
	if (SensitivityRow)
	{
		SensitivityRow->SetNumericValueSilently(Settings->GetLookSensitivity());
	}

	const bool bSeparate = Settings->GetSeparateVerticalSensitivity();

	if (SeparateVerticalRow)
	{
		SeparateVerticalRow->SetIndexSilently(bSeparate ? 1 : 0);
	}

	if (SensitivityVerticalRow)
	{
		SensitivityVerticalRow->SetNumericValueSilently(Settings->GetLookSensitivityVertical());
	}

	UpdateVerticalRowVisibility(bSeparate);

	if (InvertLookRow)
	{
		InvertLookRow->SetIndexSilently(Settings->GetInvertLookY() ? 1 : 0);
	}

	if (FieldOfViewRow)
	{
		FieldOfViewRow->SetNumericValueSilently(Settings->GetFieldOfView());
	}

	if (CameraShakeRow)
	{
		CameraShakeRow->SetNumericValueSilently(Settings->GetCameraShakeScale());
	}

	if (SprintModeRow)
	{
		SprintModeRow->SetIndexSilently(Settings->GetSprintToggle() ? 1 : 0);
	}

	if (CrouchModeRow)
	{
		CrouchModeRow->SetIndexSilently(Settings->GetCrouchToggle() ? 1 : 0);
	}
}

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

	Settings->SetSurvivalGameplayToDefaults();
	PushToPawn(Settings);
	RefreshFromSettings();
}

void USettingsGameplayWidget::UpdateVerticalRowVisibility(bool bSeparate)
{
	if (SensitivityVerticalRow)
	{
		// Collapsed et non Hidden : la ligne ne doit pas laisser un trou dans la
		// liste quand elle est inutile.
		SensitivityVerticalRow->SetVisibility(bSeparate ? ESlateVisibility::Visible : ESlateVisibility::Collapsed);
	}
}

void USettingsGameplayWidget::PushToPawn(USurvivalUserSettings* Settings)
{
	// Pas de SaveSettings ici : ecrire le .ini a chaque clic de fleche est du
	// gaspillage. C'est l'ecran de reglages qui sauvegarde en se fermant.
	Settings->ApplySurvivalSettings();
}

void USettingsGameplayWidget::HandleSensitivityChanged(int32 NewIndex)
{
	USurvivalUserSettings* Settings = USurvivalUserSettings::Get();
	if (!Settings || !SensitivityRow)
	{
		return;
	}

	Settings->SetLookSensitivity(SensitivityRow->GetNumericValue());

	// Sans axe separe, le vertical suit : on garde les deux lignes coherentes
	// pour que le joueur ne decouvre pas un ecart en activant la separation.
	if (!Settings->GetSeparateVerticalSensitivity() && SensitivityVerticalRow)
	{
		SensitivityVerticalRow->SetNumericValueSilently(Settings->GetLookSensitivityVertical());
	}

	PushToPawn(Settings);
}

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

	const bool bSeparate = NewIndex == 1;
	Settings->SetSeparateVerticalSensitivity(bSeparate);

	if (SensitivityVerticalRow)
	{
		SensitivityVerticalRow->SetNumericValueSilently(Settings->GetLookSensitivityVertical());
	}

	UpdateVerticalRowVisibility(bSeparate);
	PushToPawn(Settings);
}

void USettingsGameplayWidget::HandleSensitivityVerticalChanged(int32 NewIndex)
{
	USurvivalUserSettings* Settings = USurvivalUserSettings::Get();
	if (!Settings || !SensitivityVerticalRow)
	{
		return;
	}

	Settings->SetLookSensitivityVertical(SensitivityVerticalRow->GetNumericValue());
	PushToPawn(Settings);
}

void USettingsGameplayWidget::HandleInvertLookChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetInvertLookY(NewIndex == 1);
		PushToPawn(Settings);
	}
}

void USettingsGameplayWidget::HandleFieldOfViewChanged(int32 NewIndex)
{
	USurvivalUserSettings* Settings = USurvivalUserSettings::Get();
	if (!Settings || !FieldOfViewRow)
	{
		return;
	}

	Settings->SetFieldOfView(FieldOfViewRow->GetNumericValue());
	PushToPawn(Settings);
}

void USettingsGameplayWidget::HandleCameraShakeChanged(int32 NewIndex)
{
	USurvivalUserSettings* Settings = USurvivalUserSettings::Get();
	if (!Settings || !CameraShakeRow)
	{
		return;
	}

	Settings->SetCameraShakeScale(CameraShakeRow->GetNumericValue());
	PushToPawn(Settings);
}

void USettingsGameplayWidget::HandleSprintModeChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetSprintToggle(NewIndex == 1);
		PushToPawn(Settings);
	}
}

void USettingsGameplayWidget::HandleCrouchModeChanged(int32 NewIndex)
{
	if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get())
	{
		Settings->SetCrouchToggle(NewIndex == 1);
		PushToPawn(Settings);
	}
}

#undef LOCTEXT_NAMESPACE
