package placement

import (
	
	

	
	
)

// BalanceSymmetry centers simple nodes among neighbors aligned on one side.
func ( context.Context,  *layoutgraph.Graph) error {
	, ,  := layoutgraph.EnsureTransactionWorkGuard(, "BalanceSymmetryTransactions")
	if  != nil {
		return 
	}
	if len(.Nodes) == 0 {
		return nil
	}
	var  *layoutgraph.GraphState
	 := false
	defer func() {
		if ! &&  != nil {
			layoutgraph.RestoreGraphState(, )
		}
	}()
	// Gap normalization takes care of cases where the adjacents are on opposite ends
	// So the only case we care about is when all the adjacents are aligned on one end
	// And we just nudge to be in the middle of the alignment
	for ,  := range .Nodes {
		if !isSimple(, ) {
			continue
		}
		if len(.Edges) < 2 {
			continue
		}
		 := true
		 := make(map[*layoutgraph.Node]struct{})
		for  := 0;  < len(.Edges)-1; ++ {
			 := .Edges[]
			 := .Edges[+1]
			if .FromTableColumnIndex != nil || .ToTableColumnIndex != nil {
				continue
			}
			if .FromTableColumnIndex != nil || .ToTableColumnIndex != nil {
				continue
			}
			 := .Adjacent()
			 := .Adjacent()
			 := .Orientation()
			 := .Orientation()
			if !.SameSide() {
				 = false
				break
			}
			[] = struct{}{}
			[] = struct{}{}
		}
		if ! {
			continue
		}
		if len() < 2 {
			continue
		}
		var  layoutgraph.Nodes
		for  := range  {
			 = append(, )
		}
		if placementcost.AxisScore() != 1. {
			continue
		}
		// Fails to look symmetrical if uneven adjacents
		 := math.Inf(-1)
		for ,  := range  {
			 = math.Max(, .Width*.Height)
		}
		 := false
		for ,  := range  {
			if .Width*.Height < (0.5 * ) {
				 = true
				break
			}
		}
		if  {
			continue
		}
		 := true
		if [0].Orientation([1]).IsVertical() {
			 = false
		}
		,  := .NewRequestTransactionWithWorkGuard(, , layoutgraph.TransactionOptions{AffectContainers: true})
		if  != nil {
			return 
		}
		if  == nil {
			 = .PriorGraphState
		}
		.AddOp(func() error {
			 := .Center()
			 := .Center()
			if  {
				.MoveWithChildren(math.Floor(.X-.X), 0)
			} else {
				.MoveWithChildren(0, math.Floor(.Y-.Y))
			}
			return nil
		})
		if  := .Commit();  != nil {
			if !layoutgraph.IsCandidateRejection() {
				return 
			}
		}
	}
	 = true
	return nil
}

// isSimple reports whether node participates only as a regular placement node,
// rather than as or inside one of the engine's structured graph forms.
func isSimple( *layoutgraph.Graph,  *layoutgraph.Node) bool {
	return !(.IsContainer() || .IsTreeSentinel() || .IsClusterVessel() || .IsSequenceVessel() || .Cluster != nil || .Hierarchy != nil)
}