package graph;
import model.Diagram;
import model.Set;
import model.Association;

class DiagramAdapter {
	static function buildGraph(diagram : Diagram) : Array<GraphNode<Set>> {
		var graph : Array<GraphNode<Set>> = new Array();
		for (set in diagram.sets) {
			graph.push({ name : set.name, node : set, links : new Array() });
		}

		var tmpAssociations : Array<Association> = new Array();
		for (assoc in diagram.associations) {
			tmpAssociations.push(assoc);
		}

		while (tmpAssociations.length != 0) {
			var postpone : Bool = false;
			var assoc : Association = tmpAssociations.pop();
			var node : GraphNode<Set> = { name : assoc.name, node : assoc, links : new Array() };
			var linkedNodes : Array<GraphNode<Set>> = new Array();
			var previousLink : String = ""; //add only one link for reflexive associations
			for (link in assoc.links) {
				var ln : GraphNode<Set> = Lambda.find(graph, n -> n.name == link.set.name);
				if (ln == null) { //aggregations
					postpone = true;
				} else {
					if (ln.name != previousLink) {
						linkedNodes.push(ln);
						previousLink = ln.name;
					}
				}
			}
			if (postpone) {
				tmpAssociations.push(assoc);
			} else {
				for (ln in linkedNodes) {
					node.links.push(ln);
					ln.links.push(node);
				}
				graph.push(node);
			}
		}

		for (set in diagram.sets) {
			if (set.superset != null) {
				var node : GraphNode<Set> = Lambda.find(graph, n -> n.name == set.name);
				var ln : GraphNode<Set> = Lambda.find(graph, n -> n.name == set.superset.name);
				node.links.push(ln);
				ln.links.push(node);
			}
		}
		return graph;
	}

	public static function arrange(diagram : Diagram) {
		var graph : Array<GraphNode<Set>> = buildGraph(diagram);
		var positioner : Positioner<Set> = new Positioner(graph);
		var grid : Array<Array<Set>> = positioner.arrange();
		diagram.loadGrid(grid);
	}
}
