@tool
@icon("expression_guard.svg")
class_name ExpressionGuard
extends Guard

var expression:String = ""


func is_satisfied(context_transition:Transition, context_state:State) -> bool:
	# walk up the tree to find the root state chart node
	var root = context_state

	while is_instance_valid(root) and not root is StateChart:
		root = root.get_parent()
	
	if not is_instance_valid(root):
		push_error("Could not find root state chart node, cannot evaluate expression")
		return false

	var the_expression := Expression.new()
	var input_names = root._expression_properties.keys()

	var parse_result = the_expression.parse(expression, input_names)

	if parse_result != OK:
		push_error("Expression parse error: " + the_expression.get_error_text() + " for expression " + expression)
		return false

	# input values need to be in the same order as the input names, so we build an array
	# of values
	var input_values = []
	for input_name in input_names:
		input_values.append(root._expression_properties[input_name])

	var result = the_expression.execute(input_values)
	if the_expression.has_execute_failed():
		push_error("Expression execute error: " + the_expression.get_error_text() + " for expression: " + expression)
		return false

	if typeof(result) != TYPE_BOOL:
		push_error("Expression result is not a boolean. Returning false.")
		return false

	return result


func _get_property_list():
	var properties = []
	properties.append({
		"name": "expression",
		"type": TYPE_STRING,
		"usage": PROPERTY_USAGE_DEFAULT,
		"hint": PROPERTY_HINT_EXPRESSION
	})

	return properties
