include "primitives.alh"
include "modelling.alh"
include "object_operations.alh"
include "conformance_scd.alh"
include "utils.alh"
include "typing.alh"
include "mini_modify.alh"

String function map_P2F(model : Element, name : String):
	Element destinations
	String pick

	destinations = allAssociationDestinations(model, name, "P2F_state")

	pick = name
	while (pick == name):
		pick = set_pop(destinations)

	return pick!

Boolean function main(model : Element):
	Element all_states
	String element_name
	Boolean found_current
	Boolean flag_initial
	String new_current

	found_current = False
	new_current = read_root()

	if (set_len(allInstances(model, "FullRuntime/State")) == 0):
		// No execution in full runtime, so just flag the initial state
		flag_initial = True
		log("Searching for new initial state...")

		// And add a new time
		element_name = instantiate_node(model, "NewFullRuntime/Time", "")
		instantiate_attribute(model, element_name, "current_time", 0.0)
	else:
		flag_initial = False
		log("No searching for state!")

		// Copy the time though
		element_name = instantiate_node(model, "NewFullRuntime/Time", "")
		instantiate_attribute(model, element_name, "current_time", read_attribute(model, set_pop(allInstances(model, "FullRuntime/Time")), "current_time"))
		log("Time copied OK")

	log("Reading existing data")
	all_states = allInstances(model, "PartialRuntime/State")
	while (set_len(all_states) > 0):
		element_name = set_pop(all_states)
		if (set_len(allOutgoingAssociationInstances(model, element_name, "P2F_state")) > 0):
			// Element already exists in full, so check whether this is the current state
			log("Found existing state")
			if (read_attribute(model, map_P2F(model, element_name), "current")):
				found_current = True
				new_current = element_name
		else:
			// New state, so assume that it is not current
			log("Read value: " + cast_value(read_attribute(model, element_name, "initial")))
			if (bool_and(flag_initial, read_attribute(model, element_name, "initial"))):
				log("FOUND IT!")
				new_current = element_name
			instantiate_link(model, "P2F_state", "", element_name, element_name)
	
	log("Deleting elements...")
	all_states = allInstances(model, "NewFullRuntime/State")
	while (set_len(all_states) > 0):
		element_name = set_pop(all_states)
		model_delete_element(model, element_name)

	log("Copying elements...")
	Element all_elements
	String elem
	all_elements = dict_keys(model["model"])
	while (set_len(all_elements) > 0):
		elem = set_pop(all_elements)
		if (string_startswith(read_type(model, elem), "PartialRuntime/")):
			retype(model, elem, "NewFullRuntime/" + cast_string(list_read(string_split_nr(read_type(model, elem), "/", 1), 1)))

			if (read_type(model, elem) == "NewFullRuntime/State"):
				instantiate_attribute(model, elem, "current", elem == new_current)

	log("Setting current state...")
	String new_state
	if (found_current == False):
		if (False):
			// Prompt for new state
			output("FIX_NEW_STATE")
			new_state = input()
			all_states = allInstances(model, "NewFullRuntime/State")
			while (set_len(all_states) > 0):
				element_name = set_pop(all_states)
				if (value_eq(read_attribute(model, element_name, "name"), new_state)):
					instantiate_attribute(model, element_name, "current", True)
					break!
		else:
			// Reset to initial
			log("Resetting to initial state!")
			all_states = allInstances(model, "NewFullRuntime/State")
			while (set_len(all_states) > 0):
				element_name = set_pop(all_states)
				if (value_eq(read_attribute(model, element_name, "initial"), True)):
					log("Found initial state: " + cast_value(read_attribute(model, element_name, "name")))
					instantiate_attribute(model, element_name, "current", True)
					break!
	log("DONE!")
	return True!
