extends Node
## Sim tick loop owner. Sim runs at 20 Hz, render at 60 Hz, decoupled.
##
## Speed factor controls how many sim ticks queue per render frame:
##   1×     — 1 tick per 3 render frames  (20 ticks/s)
##   Fast   — 5 ticks per 3 render frames (~100 ticks/s)
##   Ultra  — 12 ticks per 3 render frames (~240 ticks/s)
##   Pause  — 0
##
## Saves are taken between ticks only — never mid-tick — so JobRunner mid-toil
## state round-trips cleanly. See docs/architecture.md "Time / tick model".

const SIM_HZ: int = 20
const TICK_INTERVAL_S: float = 1.0 / float(SIM_HZ)

enum Speed { PAUSE, NORMAL, FAST, ULTRA }

const SPEED_FACTOR: Dictionary = {
	Speed.PAUSE: 0,
	Speed.NORMAL: 1,
	Speed.FAST: 5,
	Speed.ULTRA: 12,
}

var current_speed: Speed = Speed.NORMAL
var tick: int = 0
var _accum: float = 0.0


func set_speed(new_speed: Speed) -> void:
	if new_speed == current_speed:
		return
	Audit.log("sim", "speed %s → %s (tick %d)" % [Speed.keys()[current_speed], Speed.keys()[new_speed], tick])
	current_speed = new_speed
	_accum = 0.0  # Prevent burst-tick after long pauses.
	EventBus.speed_changed.emit(int(new_speed))


func _process(delta: float) -> void:
	if current_speed == Speed.PAUSE:
		return
	_accum += delta * SPEED_FACTOR[current_speed]
	while _accum >= TICK_INTERVAL_S:
		_accum -= TICK_INTERVAL_S
		tick += 1
		EventBus.sim_tick.emit(tick)
