extends Node

class_name PowerNetwork

const DEBUG = false

var nodes = []
var sockets = []

var total_source = 0
var total_usage = 0
var unpowered = 0

var debugColor = Color.cyan

func _ready():
	name = "PowerNetwork"
	debugColor = Color.from_hsv(randf(), 0.8, 0.8)

remotesync func add_node(node) -> void:
	nodes.append(node)
	if "connections" in node:
		sockets.append(node)

remotesync func remove_node(node) -> void:
	var node_idx = nodes.find(node)
	if node_idx >= 0:
		nodes.remove(node_idx)
	var sock_idx = sockets.find(node)
	if sock_idx >= 0:
		sockets.remove(sock_idx)
	# Do other splitting here
	node.network = null

remotesync func join(network) -> void:
	for node in network.nodes:
		nodes.append(node)
		node.network = self
	for socket in network.sockets:
		sockets.append(socket)
		socket.network = self
	# Do other merging here
	network.queue_free()

func _physics_process(_delta: float) -> void:
	if not is_network_master():
		return
	# Recalculate power availability and usage
	total_source = 0
	total_usage = 0
	var sources = []
	var sinks = []
	# Calculate totals
	for socket in sockets:
		for connection in socket.connections:
			var manager = connection as PowerManager
			match socket.flow:
				ElectricSocket.Flow.SINK:
					total_usage += manager.power_usage
					sinks.append(manager)
				ElectricSocket.Flow.SOURCE:
					total_source += manager.power_source
					sources.append(manager)
				ElectricSocket.Flow.BIDIRECTIONAL:
					total_usage += manager.power_usage
					total_source += manager.power_source
					sinks.append(manager)
					sources.append(manager)
	# Update manager stats
	var available_supply = total_source
	unpowered = 0
	for sink in sinks:
		# Check if item can be powered this cycle
		if sink.power_usage > 0:
			if available_supply > sink.power_usage:
				available_supply -= sink.power_usage
				if not sink.powered:
					sink.rpc("set_powered", true)
			else:
				if sink.powered:
					sink.rpc("set_powered", false)
				unpowered += 1
	# Update available power to sinks
	for sink in sinks:
		sink.available = available_supply
	# Check how much we actually need to drain from sources
	var remaining_drain = total_source - available_supply
	if remaining_drain > 0:
		for source in sources:
			var source_load = source.power_source / total_source * remaining_drain
			source.power_load = source_load

func serialize():
	var node_paths = []
	var socket_paths = []
	for node in nodes:
		node_paths.append(get_path_to(node))
	for socket in sockets:
		socket_paths.append(get_path_to(socket))
	return { "nodes": node_paths, "sockets": socket_paths }

func deserialize(data):
	for node_path in data["nodes"]:
		nodes.append(get_node(node_path))
	for socket_path in data["sockets"]:
		sockets.append(get_node(socket_path))
