class_name M2UniquePlacementRegistry
extends RefCounted

## Session-memory ownership registry for positive ADT MDDF unique IDs.

var _owner_tile_by_unique_key: Dictionary = {}


## Reserves unowned positive unique IDs for one tile and returns fresh arrays.
## Unkeyed placements pass through without entering registry ownership.
func reserve(tile_key: String, m2_placements: Array) -> Dictionary:
	var filtered_placements: Array = []
	var unique_keys: Array = []
	var skipped_unique_keys: Array = []
	for placement_variant in m2_placements:
		if not (placement_variant is Dictionary):
			continue
		var placement: Dictionary = placement_variant
		var unique_key := _unique_key_for_placement(placement)
		if unique_key.is_empty():
			filtered_placements.append(placement)
			continue
		if _owner_tile_by_unique_key.has(unique_key):
			var owner_tile := String(_owner_tile_by_unique_key[unique_key])
			if owner_tile == tile_key and unique_keys.has(unique_key):
				continue
			if owner_tile != tile_key:
				if not skipped_unique_keys.has(unique_key):
					skipped_unique_keys.append(unique_key)
				continue
		_owner_tile_by_unique_key[unique_key] = tile_key
		if not unique_keys.has(unique_key):
			unique_keys.append(unique_key)
		filtered_placements.append(placement)
	return {
		"placements": filtered_placements,
		"unique_keys": unique_keys,
		"skipped_unique_keys": skipped_unique_keys,
	}


## Releases only keys currently owned by the supplied tile and returns them in
## input order so the loader can notify waiting candidate tiles.
func release(tile_key: String, unique_keys: Array) -> Array:
	var released_unique_keys: Array = []
	for unique_key_variant in unique_keys:
		var unique_key := String(unique_key_variant)
		if unique_key.is_empty() or not _owner_tile_by_unique_key.has(unique_key):
			continue
		if String(_owner_tile_by_unique_key[unique_key]) != tile_key:
			continue
		_owner_tile_by_unique_key.erase(unique_key)
		released_unique_keys.append(unique_key)
	return released_unique_keys


## Removes all reservations during world reset or renderer shutdown.
func clear() -> void:
	_owner_tile_by_unique_key.clear()


## Returns the number of currently owned positive unique IDs.
func active_count() -> int:
	return _owner_tile_by_unique_key.size()


## Returns detached, key-sorted scalar diagnostics without registry references.
func diagnostic_snapshot() -> Dictionary:
	var sorted_unique_keys: Array = _owner_tile_by_unique_key.keys()
	sorted_unique_keys.sort()
	var owners: Array = []
	for unique_key_variant in sorted_unique_keys:
		var unique_key := String(unique_key_variant)
		owners.append({
			"unique_key": unique_key,
			"tile_key": String(_owner_tile_by_unique_key[unique_key]),
		})
	return {
		"active_count": owners.size(),
		"owners": owners,
	}


func _unique_key_for_placement(placement: Dictionary) -> String:
	var unique_id := int(placement.get("unique_id", -1))
	if unique_id <= 0:
		return ""
	return "uid:%d" % unique_id
