package routing

import (
	

	
	
)

// balanceReversalRemovesCrossings permits an otherwise rejected reversal only
// when it removes crossings without increasing them for any affected route
// pair. This preserves useful uncrossing of routes that entered balancing in
// the wrong order. It is a fallback, not a second scorer for every batch.
//
// Proposed point copies also move adjacent legs and respect pointer aliases.
// The graph stays untouched until the caller accepts the entire batch.
func balanceReversalRemovesCrossings( *layoutgraph.Graph,  []*layoutgraph.EdgeSegment,  []float64,  bool,  *routeWorkGuard) (bool, error) {
	 := make(map[*geo.Point]*geo.Point)
	for ,  := range  {
		if  := .step();  != nil {
			return false, 
		}
		for ,  := range [2]*geo.Point{.Start, .End} {
			if  := .step();  != nil {
				return false, 
			}
			 := *
			if  {
				.X = []
			} else {
				.Y = []
			}
			if ,  := [];  && * !=  {
				return false, nil
			}
			[] = &
		}
	}

	if  := .add(uint64(len(.Edges)));  != nil {
		return false, 
	}
	 := make([]*layoutgraph.Edge, len(.Edges))
	var  []int
	for ,  := range .Edges {
		if  := .step();  != nil {
			return false, 
		}
		 := false
		for ,  := range .Points {
			if  := .step();  != nil {
				return false, 
			}
			if ,  := [];  && * != * {
				 = true
			}
		}
		if ! {
			continue
		}
		if .IsCurve {
			return false, nil
		}
		if  := .add(uint64(len(.Points)));  != nil {
			return false, 
		}
		 := *
		.Points = make([]*geo.Point, len(.Points))
		for ,  := range .Points {
			if  := .step();  != nil {
				return false, 
			}
			.Points[] = 
			if ,  := [];  {
				.Points[] = 
			}
			if  > 0 {
				,  := .Points[-1], .Points[-1]
				if .X != .X && .Y != .Y || .X != .Points[].X && .Y != .Points[].Y {
					return false, nil
				}
			}
		}
		[] = &
		 = append(, )
	}

	 := false
	for ,  := range  {
		if  := .step();  != nil {
			return false, 
		}
		for ,  := range .Edges {
			if  := .step();  != nil {
				return false, 
			}
			if  ==  || [] != nil &&  <  {
				continue
			}
			// A curve's control polygon cannot prove its rendered crossings.
			if .IsCurve {
				return false, nil
			}
			 := []
			if  == nil {
				 = 
			}
			,  := 0, 0
			for  := 0; +1 < len(.Edges[].Points); ++ {
				if  := .step();  != nil {
					return false, 
				}
				for  := 0; +1 < len(.Points); ++ {
					if  := .step();  != nil {
						return false, 
					}
					if isNonSharedCrossing(.Edges[], , , ) {
						++
					}
					if isNonSharedCrossing([], , , ) {
						++
					}
					// Dragged adjacent legs must not gain a new shared run.
					// Existing shared trunks may extend as a crossing is removed.
					 := balanceCollinearOverlap(.Edges[].Points[], .Edges[].Points[+1], .Points[], .Points[+1])
					 := balanceCollinearOverlap([].Points[], [].Points[+1], .Points[], .Points[+1])
					if  == 0 &&  > 0 {
						return false, nil
					}
				}
			}
			if  >  {
				return false, nil
			}
			 =  ||  < 
		}
	}
	return , nil
}

func balanceCollinearOverlap(, , ,  *geo.Point) float64 {
	if .X == .X && .X == .X && .X == .X {
		return math.Max(0, math.Min(math.Max(.Y, .Y), math.Max(.Y, .Y))-math.Max(math.Min(.Y, .Y), math.Min(.Y, .Y)))
	}
	if .Y == .Y && .Y == .Y && .Y == .Y {
		return math.Max(0, math.Min(math.Max(.X, .X), math.Max(.X, .X))-math.Max(math.Min(.X, .X), math.Min(.X, .X)))
	}
	return 0
}