#  Ham'n'Cheese
#  Copyright (C) 2023-2024 Scott Duensing <scott@kangaroopunch.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>


extends Control


@onready var settings_window            = %SettingsWindow
@onready var user_name_line_edit        = %UserNameLineEdit
@onready var network_name_line_edit     = %NetworkNameLineEdit
@onready var network_password_line_edit = %NetworkPasswordLineEdit
@onready var server_line_edit           = %ServerLineEdit
@onready var server_port_spin_box       = %ServerPortSpinBox
@onready var ip_line_edit               = %IPLineEdit
@onready var ip_check_button            = %IPCheckButton
@onready var mac_line_edit              = %MACLineEdit
@onready var mac_check_button           = %MACCheckButton
@onready var compression_check_button   = %CompressionCheckButton
@onready var auto_start_check_button    = %AutoStartCheckButton
@onready var save_settings_button       = %SaveSettingsButton


var _crypto
var _key

var uuid: String = ""
var passwords := {}


func load_settings():
	# Do we have a configuration yet?
	passwords = {}
	var config = ConfigFile.new()
	var err = config.load("user://network.cfg")
	if err != OK:
		# Assign defaults.
		user_name_line_edit.text                = "Change Me!"
		network_name_line_edit.text             = "Change Me!"
		network_password_line_edit.text         = "Change Me!"
		server_line_edit.text                   = "supernode.kangaroopunch.com"
		server_port_spin_box.value              = 7777
		ip_line_edit.text                       = "10.0.0.10"
		ip_check_button.button_pressed          = true
		ip_line_edit.editable                   = false
		mac_line_edit.text                      = "DE:AD:BE:EF:00:01"
		mac_check_button.button_pressed         = true
		mac_line_edit.editable                  = false
		compression_check_button.button_pressed = true
		auto_start_check_button.button_pressed  = false
		uuid                                    = Uuid.v4()
	else:
		# Load settings.
		user_name_line_edit.text                = config.get_value("settings", "userName",        "Change Me!")
		network_name_line_edit.text             = config.get_value("settings", "networkName",     "Change Me!")
		server_line_edit.text                   = config.get_value("settings", "server",          "supernode.kangaroopunch.com")
		server_port_spin_box.value              = config.get_value("settings", "serverPort",      7777)
		ip_line_edit.text                       = config.get_value("settings", "ipAddress",       "10.0.0.10")
		ip_check_button.button_pressed          = config.get_value("settings", "ipAutomatic",     true)
		ip_line_edit.editable                   = !ip_check_button.button_pressed
		mac_line_edit.text                      = config.get_value("settings", "macAddress",      "DE:AD:BE:EF:00:01")
		mac_check_button.button_pressed         = config.get_value("settings", "macAutomatic",    true)
		mac_line_edit.editable                  = !mac_check_button.button_pressed
		compression_check_button.button_pressed = config.get_value("settings", "compression",     true)
		auto_start_check_button.button_pressed  = config.get_value("settings", "autoStart",       false)
		uuid                                    = config.get_value("settings", "identity",        Uuid.v4())
		# Load passwords.
		passwords["networkPassword"] = ""
		if config.has_section("passwords"):
			for key in config.get_section_keys("passwords"):
				passwords[key] = config.get_value("passwords", key).hex_decode()
				passwords[key] = _crypto.decrypt(_key, passwords[key]).get_string_from_utf8()
		network_password_line_edit.text = passwords["networkPassword"]


func save_settings():
	# Validate IP address, if needed.
	if !ip_check_button.button_pressed:
		var ipCheck = RegEx.create_from_string("^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$")
		if ipCheck.search(ip_line_edit.text) == null:
			# Not an IP address.
			await Dialog.alert("Invalid IP Address", "The IP address entered is invalid.", settings_window)
			return

	# Validate MAC address, if needed.
	if !mac_check_button.button_pressed:
		var macCheck = RegEx.create_from_string("^(?:[[:xdigit:]]{2}([-:]))(?:[[:xdigit:]]{2}\\1){4}[[:xdigit:]]{2}$")
		if macCheck.search(mac_line_edit.text) == null:
			# Not a MAC address.
			await Dialog.alert("Invalid MAC Address", "The MAC address entered is invalid.", settings_window)
			return

	# Save it.
	var config = ConfigFile.new()
	# Settings.
	config.set_value("settings", "userName",        user_name_line_edit.text)
	config.set_value("settings", "networkName",     network_name_line_edit.text)
	config.set_value("settings", "server",          server_line_edit.text)
	config.set_value("settings", "serverPort",      server_port_spin_box.value)
	config.set_value("settings", "ipAddress",       ip_line_edit.text)
	config.set_value("settings", "ipAutomatic",     ip_check_button.button_pressed)
	config.set_value("settings", "macAddress",      mac_line_edit.text)
	config.set_value("settings", "macAutomatic",    mac_check_button.button_pressed)
	config.set_value("settings", "compression",     compression_check_button.button_pressed)
	config.set_value("settings", "autoStart",       auto_start_check_button.button_pressed)
	#config.set_value("settings", "position",        DisplayServer.window_get_position())
	config.set_value("settings", "identity",        uuid)
	# Passwords.
	passwords["networkPassword"] = network_password_line_edit.text
	for password in passwords:
		var encrypted = _crypto.encrypt(_key, passwords[password].to_utf8_buffer())
		config.set_value("passwords", password, encrypted.hex_encode())
	config.save("user://network.cfg")


func _init_crypto():
	_crypto = Crypto.new()
	_key = CryptoKey.new()
	if !FileAccess.file_exists("user://rsa.key") or !FileAccess.file_exists("user://rsa.crt"):
		var cert = X509Certificate.new()
		_key = _crypto.generate_rsa(4096)
		cert = _crypto.generate_self_signed_certificate(_key, "CN=kangaroopunch.com,O=Kangaroo Punch Studios,C=US")
		_key.save("user://rsa.key")
		cert.save("user://rsa.crt")
	else:
		_key.load("user://rsa.key")


func _on_ip_check_button_toggled(_toggled_on):
	ip_line_edit.editable = !ip_check_button.button_pressed


func _on_mac_check_button_toggled(_toggled_on):
	mac_line_edit.editable = !mac_check_button.button_pressed


func _on_save_settings_button_pressed():
	save_settings()
	settings_window.visible = false


func _on_settings_window_close_requested():
	settings_window.visible = false


func _ready():
	_init_crypto()
	load_settings()

