class_name SimulationDefinitions
extends RefCounted

const ACTION_PATHS := [
	"res://simulation/definitions/actions/gather_food.tres",
	"res://simulation/definitions/actions/gather_wood.tres",
	"res://simulation/definitions/actions/patrol.tres",
	"res://simulation/definitions/actions/study.tres",
	"res://simulation/definitions/actions/eat.tres",
	"res://simulation/definitions/actions/rest.tres",
	"res://simulation/definitions/actions/wander.tres",
	"res://simulation/definitions/actions/deposit_food.tres",
	"res://simulation/definitions/actions/withdraw_food.tres"
]

const PROFESSION_PATHS := [
	"res://simulation/definitions/professions/farmer.tres",
	"res://simulation/definitions/professions/woodcutter.tres",
	"res://simulation/definitions/professions/guard.tres",
	"res://simulation/definitions/professions/scholar.tres",
	"res://simulation/definitions/professions/wanderer.tres"
]


static func get_actions() -> Array[ActionDefinition]:
	var definitions: Array[ActionDefinition] = []
	for path in ACTION_PATHS:
		var definition := load(path) as ActionDefinition
		if definition != null:
			definitions.append(definition)
	return definitions


static func get_professions() -> Array[ProfessionDefinition]:
	var definitions: Array[ProfessionDefinition] = []
	for path in PROFESSION_PATHS:
		var definition := load(path) as ProfessionDefinition
		if definition != null:
			definitions.append(definition)
	return definitions


static func get_action(action_id: StringName) -> ActionDefinition:
	for definition in get_actions():
		if definition.action_id == action_id:
			return definition
	return null


static func get_profession(profession_id: StringName) -> ProfessionDefinition:
	for definition in get_professions():
		if definition.profession_id == profession_id:
			return definition
	return null


static func get_profession_ids() -> Array[StringName]:
	var ids: Array[StringName] = []
	for definition in get_professions():
		ids.append(definition.profession_id)
	return ids


static func validate() -> Array[String]:
	var errors: Array[String] = []
	if get_actions().size() != ACTION_PATHS.size():
		errors.append("One or more ActionDefinition resources failed to load")
	if get_professions().size() != PROFESSION_PATHS.size():
		errors.append("One or more ProfessionDefinition resources failed to load")
	var action_ids := {}
	for definition in get_actions():
		for error in definition.validate():
			errors.append("ActionDefinition: " + error)
		if action_ids.has(definition.action_id):
			errors.append("Duplicate action_id '%s'" % definition.action_id)
		action_ids[definition.action_id] = true

	var profession_ids := {}
	for definition in get_professions():
		for error in definition.validate():
			errors.append("ProfessionDefinition: " + error)
		if profession_ids.has(definition.profession_id):
			errors.append("Duplicate profession_id '%s'" % definition.profession_id)
		profession_ids[definition.profession_id] = true

	for definition in get_actions():
		if (
			not definition.preferred_profession_id.is_empty()
			and not profession_ids.has(definition.preferred_profession_id)
		):
			errors.append(
				(
					"Action '%s' references unknown profession '%s'"
					% [definition.action_id, definition.preferred_profession_id]
				)
			)
		if (
			definition.target_type == SimulationIds.TARGET_RESOURCE
			and not action_ids.has(definition.resource_action_id)
		):
			errors.append(
				(
					"Action '%s' references unknown resource action '%s'"
					% [definition.action_id, definition.resource_action_id]
				)
			)
	return errors
