package engine

import (
	
	
	

	
	
	
)

// CompoundCandidate gives the selected drawing at most one rigid-container
// placement trial. It never runs another full seed pipeline. The adapter must
// validate and compare the completed proposal against the ordinary incumbent.
func ( context.Context,  *layoutgraph.Graph) (*layoutgraph.Graph, error) {
	if  == nil ||  == nil {
		return nil, fmt.Errorf("TALA compound candidate requires a context and graph")
	}
	if  := .Err();  != nil {
		return nil, 
	}
	if len(.Nodes) > 128 || len(.Edges) > 256 || len(.Containers[nil]) < 3 || len(.Containers[nil]) > 64 {
		return , nil
	}
	 := false
	for ,  := range .Containers[nil] {
		 =  || .IsContainer()
	}
	if ! || .HasFixedNode() {
		return , nil
	}
	,  := layoutgraph.Clone(, )
	if  != nil {
		return nil, 
	}
	// This is a deterministic post-selection proposal, independent of seed
	// completion order. Requested seeds still run exactly once each.
	,  := hierarchy.PlaceCompound(, , rand.New(rand.NewSource(0)))
	if  != nil {
		return nil, 
	}
	if ! {
		return , nil
	}
	// This is an outer-flow refinement. Avoid a routing trial when its block
	// arrangement makes more external connections cross between disjoint lanes.
	// This is an admission heuristic, not a bound on the completed layout score:
	// routing and labels still determine whether an admitted proposal is kept.
	 := compoundCrossAxisDetours() > compoundCrossAxisDetours()
	if  := .Err();  != nil {
		return nil, 
	}
	if  {
		return , nil
	}
	if  := reroutePlaced(, );  != nil {
		return nil, 
	}
	,  := .BoundingBox()
	if  != nil &&  != nil && (.X-.X > maxGraphSize || .Y-.Y > maxGraphSize) {
		return , nil
	}
	return , nil
}

// compoundCrossAxisDetours counts external connections whose outer blocks have
// disjoint projections perpendicular to the flow. Their logical blocks offer
// no shared lane along that flow; labels and visual modifiers are not included.
// Endpoints inside the same rigid block do not participate: their arrangement
// is unchanged by this proposal.
func compoundCrossAxisDetours( *layoutgraph.Graph) int {
	 := make(map[*layoutgraph.Node]*layoutgraph.Node, len(.Nodes))
	for ,  := range .Nodes {
		 := 
		for .Container != nil {
			 = .Container
		}
		[] = 
	}
	 := .Direction(nil).IsHorizontal()
	 := 0
	for ,  := range .Edges {
		,  := [.From], [.To]
		if  ==  {
			continue
		}
		if  {
			if .TopLeft.Y+.Height < .TopLeft.Y || .TopLeft.Y+.Height < .TopLeft.Y {
				++
			}
		} else if .TopLeft.X+.Width < .TopLeft.X || .TopLeft.X+.Width < .TopLeft.X {
			++
		}
	}
	return 
}

func reroutePlaced( context.Context,  *layoutgraph.Graph) error {
	 := newPipeline(, 0, false)
	.resetFullLayoutRouteState()
	// Reuse routing and label cleanup on placed nodes without regrouping,
	// rescaling, or invoking another full seed attempt.
	 := []func(context.Context) error{
		.edgeRoutingStage, .simplifyEdgeRoutes, .swapEdgePorts,
		.straightEdgesFallback, .balanceEdgeSegments,
		.fixClusterEdgeBranching, .traceEdgesToShapeBorder,
		.reorderDuplicates, .placeLabels,
	}
	for ,  := range  {
		if  := .Err();  != nil {
			return 
		}
		if  := ();  != nil {
			return 
		}
	}
	// Authored fixed origins have already had prescale padding removed.
	if !.HasFixedNode() {
		placement.Normalize()
	}
	return .Err()
}