class_name StorageStateRecord
extends RefCounted

const SCHEMA_VERSION := 1

var data: Dictionary


func _init(record_data: Dictionary = {}) -> void:
	data = record_data.duplicate(true)


static func create(
	storage_id: StringName, initial_amounts: Dictionary, capacity: float = 100.0
) -> StorageStateRecord:
	return StorageStateRecord.new(
		{
			"schema_version": SCHEMA_VERSION,
			"storage_id": String(storage_id),
			"amounts": initial_amounts.duplicate(true),
			"capacity": capacity
		}
	)


static func from_dictionary(record_data: Dictionary) -> StorageStateRecord:
	if int(record_data.get("schema_version", -1)) != SCHEMA_VERSION:
		return null
	if not record_data.has_all(["storage_id", "amounts", "capacity"]):
		return null
	if String(record_data["storage_id"]).is_empty():
		return null
	if not record_data["amounts"] is Dictionary:
		return null
	var normalized := record_data.duplicate(true)
	normalized["schema_version"] = SCHEMA_VERSION
	normalized["capacity"] = float(record_data["capacity"])
	var normalized_amounts := {}
	for item_id in record_data["amounts"]:
		normalized_amounts[String(item_id)] = float(record_data["amounts"][item_id])
	normalized["amounts"] = normalized_amounts
	return StorageStateRecord.new(normalized)


func get_storage_id() -> StringName:
	return StringName(data["storage_id"])


func get_amount(item_id: StringName) -> float:
	return float(data["amounts"].get(String(item_id), 0.0))


func get_total_amount() -> float:
	var total := 0.0
	for amount in data["amounts"].values():
		total += float(amount)
	return total


func deposit(item_id: StringName, requested_amount: float) -> float:
	var accepted := minf(
		maxf(requested_amount, 0.0), maxf(float(data["capacity"]) - get_total_amount(), 0.0)
	)
	if accepted <= 0.0:
		return 0.0
	data["amounts"][String(item_id)] = get_amount(item_id) + accepted
	return accepted


func withdraw(item_id: StringName, requested_amount: float) -> float:
	var removed := minf(maxf(requested_amount, 0.0), get_amount(item_id))
	if removed <= 0.0:
		return 0.0
	data["amounts"][String(item_id)] = get_amount(item_id) - removed
	return removed


func to_dictionary() -> Dictionary:
	return data.duplicate(true)
