extends VBoxContainer

signal changed
signal leave_stage

var has_stage:bool = false:
	set(stage):
		has_stage = stage
		preset_selected = preset_selected

@export_file(".json") var settings_path = "user://video_settings.json"

@export_enum("None", "Performance", "Balanced", "Quality") var preset_selected:int = 2:
	set(value):
		preset_selected = value
		if has_stage: 
			match preset_selected:
				1: %PerformancePreset.grab_focus()
				2: %BalancedPreset.grab_focus()
				3: %QualityPreset.grab_focus()
				_: %FullscreenMode.grab_focus()

@export var window_mode: DisplayServer.WindowMode = DisplayServer.WindowMode.WINDOW_MODE_FULLSCREEN:
	set(value):
		window_mode = value
		changed.emit()
@onready var fullscreen_selector: OptionButton = %FullscreenMode

@export_range(0.5, 2) var render_scale: float = 1:
	set(value):
		render_scale = value
		changed.emit()
@onready var scale_selector: SpinBox = %RenderScale

@export var upscale_mode: RenderingServer.ViewportScaling3DMode = RenderingServer.ViewportScaling3DMode.VIEWPORT_SCALING_3D_MODE_BILINEAR :
	set(value):
		upscale_mode = value
		changed.emit()
@onready var upscale_selector: OptionButton = %SuperResolution

@export_range(30, 144) var max_fps: int = 60:
	set(value):
		max_fps = value
		changed.emit()
@onready var fps_enabler: CheckBox = %EnableFps
var fps_enabled: bool:
	set(value):
		fps_enabled = value
			
@onready var fps_selector: SpinBox = %MaxFps

@export_enum("low", "medium", "high", "ultra") var lighting_quality: int = 3:
	set(value):
		lighting_quality = value
		changed.emit()
@onready var lightning_selector: OptionButton = %LightingQuality

@export_enum("low", "medium", "high") var shadow_quality: int = 3:
	set(value):
		shadow_quality = value
		changed.emit()
@onready var shadow_selector: OptionButton = %ShadowQuality

@export_enum("no", "1x", "2x", "4x", "8x") var texture_filtering:int = 3:
	set(value):
		texture_filtering = value
		changed.emit()
@onready var texture_selector: OptionButton = %TextureFiltering

@export_enum("no", "1x", "2x", "4x") var msaa = 0:
	set(value):
		msaa = value
		changed.emit()
@onready var msaa_selector: OptionButton = %AntiAlaising

@export var vsync_mode: DisplayServer.VSyncMode = DisplayServer.VSyncMode.VSYNC_ENABLED:
	set(value):
		vsync_mode = value
		changed.emit()
@onready var vsync_selector: OptionButton = %vSync

var has_changed: bool = false:
	set(value):
		has_changed = value
		preset_selected = 0
		if has_changed:
			%ExitButton.text = "discard"
		else:
			%ExitButton.text = "close"

func _ready() -> void:
	load_settings()
	
	propagate_settings()
	
	fullscreen_selector.item_selected.connect(func(value): window_mode = value)
	scale_selector.value_changed.connect(func(value): render_scale = value)
	upscale_selector.item_selected.connect(func(value): upscale_mode = value)
	lightning_selector.item_selected.connect(func(value): lighting_quality = value)
	shadow_selector.item_selected.connect(func(value): shadow_quality = value)
	texture_selector.item_selected.connect(func(value): texture_filtering = value)
	msaa_selector.item_selected.connect(func(value): msaa = value)
	vsync_selector.item_selected.connect(func(value): vsync_mode = value)
	
	scale_selector.value_changed.connect(func(value): render_scale= value)
	fps_selector.value_changed.connect(func(value): max_fps = value)
	fps_enabler.toggled.connect(func(value): fps_enabled = value)
	
	changed.connect(func():has_changed = true)
	
	preset_selected = preset_selected
	
	%ExitButton.pressed.connect(_on_exit_button_pressed)
	%ConfirmExit.pressed.connect(_on_exit_confirmed)
	%ConfirmSave.pressed.connect(_on_confirm_button_pressed)
	%ConfirmAbort.pressed.connect($Popup.hide)

func load_settings():
	
	if FileAccess.file_exists(settings_path):
		var file = FileAccess.open(settings_path, FileAccess.READ)
		var raw_json = FileAccess.get_file_as_string(settings_path)
		file.close()
		var parsed: Dictionary = JSON.parse_string(raw_json)
		
		for key in parsed.keys():
			set(key, parsed[key])

func propagate_settings():
	fullscreen_selector.select(window_mode)
	scale_selector.value = render_scale
	upscale_selector.select(upscale_mode)
	fps_enabler.button_pressed = fps_enabled
	fps_selector.value = max_fps
	lightning_selector.select(lighting_quality)
	shadow_selector.select(shadow_quality)
	texture_selector.select(texture_filtering)
	msaa_selector.select(msaa)
	vsync_selector.select(vsync_mode)


func save_settings():
	var out_dict = {
		"window_mode": window_mode,
		"render_scale": render_scale,
		"upscale_mode": upscale_mode,
		"max_fps": max_fps,
		"lighting_quality": lighting_quality,
		"shadow_quality": shadow_quality,
		"texture_filtering": texture_filtering,
		"msaa": msaa,
		"vsync_mod": vsync_mode,
		"preset_selected": preset_selected
	}
	
	
	var file = FileAccess.open(settings_path, FileAccess.WRITE)
	file.store_string(JSON.stringify(out_dict))
	file.close()
	
	has_changed = false

func _on_exit_confirmed() -> void:
	leave_stage.emit()
	State.leave_stage(self)
	
func _on_exit_button_pressed() -> void:
	if has_changed:
		$Popup.show()
	else:
		leave_stage.emit()
		State.leave_stage(self)

func _on_confirm_button_pressed() -> void:
	ProjectSettings.set_setting("display/window/size/mode", fullscreen_selector)
	ProjectSettings.set_setting("rendering/scaling_3d/scale", render_scale)
	ProjectSettings.set_setting("rendering/scaling_3d/mode", upscale_mode)
	ProjectSettings.set_setting("application/run/max_fps", max_fps if fps_enabled else 0)
	match lighting_quality:
		0:
			State.ssil_enable = false
			State.sdfgi_enable = false
			ProjectSettings.set_setting("rendering/shading/overrides/force_lambert_over_burley", true)
		1: 
			State.ssil_enable = false
			State.sdfgi_enable = true
			ProjectSettings.set_setting("rendering/global_illumination/sdfgi/probe_ray_count", 8)
			ProjectSettings.set_setting("rendering/shading/overrides/force_lambert_over_burley", true)
		2:
			State.ssil_enable = false
			State.sdfgi_enable = true
			ProjectSettings.set_setting("rendering/global_illumination/sdfgi/probe_ray_count", 16)
			ProjectSettings.set_setting("rendering/shading/overrides/force_lambert_over_burley", false)
		3:
			State.ssil_enable = true
			State.sdfgi_enable = true
			ProjectSettings.set_setting("rendering/global_illumination/sdfgi/probe_ray_count", 32)
			ProjectSettings.set_setting("rendering/shading/overrides/force_lambert_over_burley", false)
	ProjectSettings.set_setting("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality", shadow_quality)
	ProjectSettings.set_setting("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality", shadow_quality)
	ProjectSettings.set_setting("rendering/textures/default_filters/anisotropic_filtering_level", texture_filtering)
	ProjectSettings.set_setting("rendering/anti_aliasing/quality/msaa_3d", msaa)
	ProjectSettings.set_setting("display/window/vsync/vsync_mode", vsync_mode)
	
	save_settings()

func _on_performance_preset_pressed() -> void:
	render_scale = 0.8
	max_fps = 60
	fps_enabled = true
	lighting_quality = 0
	shadow_quality = 0
	texture_filtering = 1
	msaa = 0
	vsync_mode = 0
	
	propagate_settings()
	
	preset_selected = 1

func _on_balanced_preset_pressed() -> void:
	render_scale = 1
	max_fps = 60
	fps_enabled = true
	lighting_quality = 2
	shadow_quality = 1
	texture_filtering = 3
	msaa = 1
	vsync_mode = 1
	
	propagate_settings()
	
	preset_selected = 2

func _on_quality_preset_pressed() -> void:
	render_scale = 1
	max_fps = 60
	fps_enabled = false
	lighting_quality = 3
	shadow_quality = 2
	texture_filtering = 4
	msaa = 3
	vsync_mode = 1
	
	propagate_settings()
	
	preset_selected = 3
