extends Node
## Autosave trigger — owns periodic + app-pause + focus-loss autosave logic.
##
## Does NOT own the write logic (that is SaveSystem.save_to_slot). This node
## only decides *when* to fire an autosave.  It gates on _busy so we never
## start a save while another save/load is in-flight.
##
## Periodic cadence: every AUTOSAVE_INTERVAL_TICKS sim ticks (~5 in-game minutes
## at 20 Hz × Fast speed).  The tick counter resets on every save_finished so
## that a manual save also resets the periodic clock.
##
## App-pause (mobile) and focus-loss (desktop) are immediate triggers.

const AUTOSAVE_INTERVAL_TICKS: int = 6000  # 20 Hz × 300 s = 5 in-game minutes

## Set true while a save or load is in progress so we don't re-enter.
var _busy: bool = false
## Counts sim ticks since the last autosave (or last save_finished, whichever
## came last) so we respect the interval even across manual saves.
var _ticks_since_save: int = 0


func _ready() -> void:
	EventBus.sim_tick.connect(_on_sim_tick)
	EventBus.save_started.connect(_on_save_started)
	EventBus.save_finished.connect(_on_save_finished)
	EventBus.load_started.connect(_on_load_started)
	EventBus.load_finished.connect(_on_load_finished)
	Audit.log("autosave", "Autosave ready — interval %d ticks" % AUTOSAVE_INTERVAL_TICKS)


func _notification(what: int) -> void:
	match what:
		NOTIFICATION_APPLICATION_PAUSED:
			# Mobile: app sent to background — save immediately.
			_trigger_autosave("app-pause")
		NOTIFICATION_WM_WINDOW_FOCUS_OUT:
			# Desktop: window lost focus — save immediately.
			_trigger_autosave("focus-loss")


# ── signal handlers ───────────────────────────────────────────────────────────

func _on_sim_tick(tick_number: int) -> void:
	if _busy:
		return
	_ticks_since_save += 1
	if _ticks_since_save >= AUTOSAVE_INTERVAL_TICKS:
		_trigger_autosave("periodic save at tick %d" % tick_number)


func _on_save_started(_slot: StringName) -> void:
	_busy = true


func _on_save_finished(_slot: StringName, _ok: bool) -> void:
	_busy = false
	# Reset the periodic counter so any save (manual or auto) restarts the clock.
	_ticks_since_save = 0


func _on_load_started(_slot: StringName) -> void:
	_busy = true


func _on_load_finished(_slot: StringName, _ok: bool, _seconds: int) -> void:
	_busy = false
	_ticks_since_save = 0


# ── helpers ───────────────────────────────────────────────────────────────────

func _trigger_autosave(reason: String) -> void:
	if _busy:
		Audit.log("autosave", "skipped (%s) — save already in progress" % reason)
		return
	Audit.log("autosave", reason)
	SaveSystem.save_to_slot(&"autosave")
