# Hurry Curry! - a game about cooking
# Copyright (C) 2026 Hurry Curry! Contributors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, version 3 of the License only.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
class_name InputSetting
extends GameSetting

const INPUT_VALUE_NODE_SCENE = preload("res://gui/menus/settings/input/input_value_node.tscn")

func _init(new_id: String):
	super(new_id)
	default = InputMap.action_get_events(new_id).duplicate(true)

func create_row():
	var row = super()
	row.value_node = INPUT_VALUE_NODE_SCENE.instantiate()
	# Manual initial update without update() since that needs to wait for _ready
	row.value_node.value = Settings.read(key)
	Settings.hook_changed(key, row.value_node,
		func(value):
			if is_instance_valid(row):
				row.value_node.value = value
				row.value_node.update()
	)
	row.value_node.changed.connect(func(): Settings.write(key, row.value_node.value))
	return row

func save(d: Dictionary):
	var value = Settings.read(key)
	if event_arrays_equal(default, value): return
	var out = []
	for ev in value:
		if ev is InputEventJoypadButton: out.push_back(["joypad_button", ev.button_index])
		elif ev is InputEventJoypadMotion: out.push_back(["joypad_motion", ev.axis])
		elif ev is InputEventMouseButton: out.push_back(["mouse_button", ev.button_index])
		elif ev is InputEventKey: out.push_back(["key", ev.physical_keycode])
	d[key] = out

func load(d: Dictionary):
	if d.has(key) and typeof(d[key]) == typeof(default):
		var out = []
		for ev in d[key]:
			if ev[0] == "joypad_button":
				var k = InputEventJoypadButton.new()
				k.button_index = int(ev[1])
				out.push_back(k)
			elif ev[0] == "joypad_motion":
				var k = InputEventJoypadMotion.new()
				k.axis = int(ev[1])
				out.push_back(k)
			elif ev[0] == "mouse_button":
				var k = InputEventMouseButton.new()
				k.button_index = int(ev[1])
				out.push_back(k)
			elif ev[0] == "key":
				var k = InputEventKey.new()
				k.physical_keycode = int(ev[1])
				out.push_back(k)
		Settings.write_unchecked(key, out)
	elif default != null:
		Settings.write_unchecked(key, default)

# TODO types: static func event_arrays_equal(a1: Array[InputEvent], a2: Array[InputEvent]) -> bool:
static func event_arrays_equal(a1, a2) -> bool:
	if a1.size() != a2.size(): return false
	for e1 in a1:
		var has = false
		for e2 in a2:
			has = has or events_equal(e1, e2)
		if not has: return false
	return true

static func events_equal(e1: InputEvent, e2: InputEvent) -> bool:
	if e1 is InputEventKey and e2 is InputEventKey:
		return e1.physical_keycode == e2.physical_keycode
	elif e1 is InputEventMouseButton and e2 is InputEventMouseButton:
		return e1.button_index == e2.button_index
	elif e1 is InputEventJoypadButton and e2 is InputEventJoypadButton:
		return e1.button_index == e2.button_index
	elif e1 is InputEventJoypadMotion and e2 is InputEventJoypadMotion:
		return e1.axis == e2.axis
	return false
