package routing

import (
	
	

	
	
	
	
)

func ( *routeWorkGuard) ( int) error {
	if  < 2 {
		return .step()
	}
	// Go's comparison sort is O(n log n). Reserve that worst-case work before
	// entering the non-interruptible standard-library sort, while retaining its
	// exact ordering behavior for equal values.
	for  := 1;  < ; {
		if  := .add(uint64());  != nil {
			return 
		}
		if  > /2 {
			break
		}
		 *= 2
	}
	return .check()
}

func portEdgesGuarded( layoutgraph.Edges,  *layoutgraph.Node,  workBudget) (map[geo.Point][]*layoutgraph.Edge, error) {
	 := make(map[geo.Point][]*layoutgraph.Edge)
	for ,  := range  {
		if  := .step();  != nil {
			return nil, 
		}
		var  *geo.Point
		switch {
		case .From == :
			 = .SourcePort()
		case .To == :
			 = .TargetPort()
		default:
			continue
		}
		if  != nil {
			[*] = append([*], )
		}
	}
	return , nil
}

func edgeHasDuplicateInGuarded( *layoutgraph.Edge,  []*layoutgraph.Edge,  workBudget) (bool, error) {
	for ,  := range  {
		if  := .step();  != nil {
			return false, 
		}
		if .IsDuplicateOf() {
			return true, nil
		}
	}
	return false, nil
}

func tryStraightEdgeFallbackGuarded( *layoutgraph.Graph,  *layoutgraph.Edge,  *routeWorkGuard) error {
	if  := .step();  != nil {
		return 
	}
	,  := estimateRouteCostGuarded(layoutgraph.Edges(.Edges), , )
	if  != nil {
		return 
	}
	, , ,  := routeLineGuarded(, , .Edges, nil, )
	if  != nil {
		if layoutgraph.IsCandidateRejection() {
			// A straight replacement is optional. Preserve the current route
			// when no valid line exists.
			return nil
		}
		return 
	}

	if len(.Points) == 4 && geo.EuclideanDistance(
		.Points[1].X,
		.Points[1].Y,
		.Points[2].X,
		.Points[2].Y,
	) <= lowerJitterThreshold {
		 /= nonOrthogonalFactor
	}
	if  := .step();  != nil {
		return 
	}
	if  <  {
		.Points = []*geo.Point{, }
	}
	return nil
}

func filterEdgeAncestorsGuarded( *layoutgraph.Edge,  layoutgraph.Nodes,  workBudget) (layoutgraph.Nodes, error) {
	 := make(layoutgraph.Nodes, 0, len())
	for ,  := range  {
		if  := .step();  != nil {
			return nil, 
		}
		if  != .From &&  != .To && (.From.IsDescendantOf() || .To.IsDescendantOf()) {
			continue
		}
		 = append(, )
	}
	return , nil
}

func sourceAndTargetClusterNodesGuarded( *layoutgraph.Graph, ,  *layoutgraph.Node,  workBudget) (map[*layoutgraph.Node]bool, map[*layoutgraph.Node]bool, error) {
	 := make(map[*layoutgraph.Node]bool)
	 := make(map[*layoutgraph.Node]bool)

	for ,  := range .Clusters {
		if  := .step();  != nil {
			return nil, nil, 
		}
		 := false
		 := false
		for ,  := range .Nodes {
			if  := .step();  != nil {
				return nil, nil, 
			}
			if  ==  {
				 = true
			}
			if  ==  {
				 = true
			}
		}
		if  {
			for ,  := range .Nodes {
				if  := .step();  != nil {
					return nil, nil, 
				}
				if  !=  {
					[] = true
				}
			}
		}
		if  {
			for ,  := range .Nodes {
				if  := .step();  != nil {
					return nil, nil, 
				}
				if  !=  {
					[] = true
				}
			}
		}
	}
	return , , nil
}

func overlappingEdgesGuarded(,  *geo.Point,  []*layoutgraph.Edge,  workBudget) ([]*layoutgraph.Edge, error) {
	 := make([]*layoutgraph.Edge, 0)
	for ,  := range  {
		if  := .step();  != nil {
			return nil, 
		}
		for  := 0;  < len(.Points)-1; ++ {
			if  := .step();  != nil {
				return nil, 
			}
			if isVerticalOrHorizontalOverlap(, , .Points[], .Points[+1]) {
				 = append(, )
				break
			}
		}
	}
	return , nil
}

func edgeCanOverlapEdgesGuarded( *layoutgraph.Edge,  []*layoutgraph.Edge, ,  map[*layoutgraph.Node]bool,  workBudget) (bool, error) {
	if len() == 0 {
		// add(0) polls the context, so the general path below performs eleven
		// identical polls before edgeCanOverlapEdges returns true. A standard
		// cancellable context exposes a Done signal, making one poll sufficient.
		// Retain the legacy sequence for synthetic contexts that expose
		// cancellation only through Err.
		if ,  := .(*routeSearchWorkGuard);  && .done != nil {
			if  := .check();  != nil {
				return false, 
			}
			return true, nil
		}
	}
	// edgeCanOverlapEdges makes a bounded number of full passes over otherEdges.
	// Reserve its worst-case comparisons before calling it so ordinary output and
	// unstable-order behavior remain byte-for-byte unchanged.
	for  := 0;  < 10; ++ {
		if  := .add(uint64(len()));  != nil {
			return false, 
		}
	}
	if  := .check();  != nil {
		return false, 
	}
	return edgeCanOverlapEdges(, , , ), nil
}

func positionedArrowheadLabelCostGuarded(
	 labeling.PositionedArrowheadLabel,
	 []*layoutgraph.Node,
	 []labeling.PositionedArrowheadLabel,
	 []*Route,
	 []*layoutgraph.Edge,
	 workBudget,
) (float64, error) {
	for ,  := range  {
		if  := .step();  != nil {
			return 0, 
		}
		if .Edge == .Edge && .IsTarget == .IsTarget {
			continue
		}
		if .Box.Overlaps(.Box) {
			if .Text == .Text {
				continue
			}
			return math.Inf(1), nil
		}
	}

	 := .Edge.From.Graph
	 := &layoutgraph.Node{Box: .Box, Graph: }
	 := 0
	for ,  := range  {
		if  := .step();  != nil {
			return 0, 
		}
		if .LabelBoxesOverlap(, label.PADDING) {
			++
		}
	}
	 := 4 * .TurnCost() * float64()

	 := 0
	for ,  := range  {
		if  := .step();  != nil {
			return 0, 
		}
		if .GEdge == .Edge {
			continue
		}
		for  := 1;  < len(.OVGNodes); ++ {
			if  := .step();  != nil {
				return 0, 
			}
			if .OverlapsLine(.OVGNodes[-1].Point, .OVGNodes[].Point, 0) {
				++
				break
			}
		}
	}
	for ,  := range  {
		if  := .step();  != nil {
			return 0, 
		}
		if  == .Edge {
			continue
		}
		for  := 1;  < len(.Points); ++ {
			if  := .step();  != nil {
				return 0, 
			}
			if .OverlapsLine(.Points[-1], .Points[], 0) {
				++
				break
			}
		}
	}
	 += .TurnCost() * float64()
	return , nil
}

func edgeIsStraightGuarded( *layoutgraph.Edge,  *routeWorkGuard) (bool, error) {
	if len(.Points) < 2 {
		return false, .step()
	}
	 := .Points[0]
	 := .Points[1]
	for  := 2;  < len(.Points); ++ {
		if  := .step();  != nil {
			return false, 
		}
		if orientation(, , .Points[]) != 0 {
			return false, nil
		}
		 = 
		 = .Points[]
	}
	return true, nil
}

func edgeHasOverlappingEndGuarded( *layoutgraph.Edge,  *routeWorkGuard) (bool, error) {
	 := .Points[0]
	 := .Points[len(.Points)-1]
	for ,  := range .From.Edges {
		if  := .step();  != nil {
			return false, 
		}
		if  !=  && (nonNilEquals(.Points[0], ) || nonNilEquals(.Points[len(.Points)-1], )) {
			return true, nil
		}
	}
	for ,  := range .To.Edges {
		if  := .step();  != nil {
			return false, 
		}
		if  !=  && (nonNilEquals(.Points[0], ) || nonNilEquals(.Points[len(.Points)-1], )) {
			return true, nil
		}
	}
	return false, nil
}

func reorderDuplicatesInEdgesGuarded( []*layoutgraph.Edge,  *routeWorkGuard) error {
	for ,  := range  {
		if  := .step();  != nil {
			return 
		}
		if .HasTableColumn() || .Label == nil {
			continue
		}
		,  := edgeIsStraightGuarded(, )
		if  != nil {
			return 
		}
		if ! {
			continue
		}
		,  := edgeHasOverlappingEndGuarded(, )
		if  != nil {
			return 
		}

		 := make([]int, 0)
		for ,  := range  {
			if  := .step();  != nil {
				return 
			}
			if  ==  || !.IsDuplicateOf() {
				continue
			}
			,  := edgeIsStraightGuarded(, )
			if  != nil {
				return 
			}
			if ! {
				continue
			}
			 := false
			if  {
				 = true
			} else {
				,  = edgeHasOverlappingEndGuarded(, )
				if  != nil {
					return 
				}
			}
			if  {
				 := .SourceArrowhead
				 := .TargetArrowhead
				if .From == .To {
					,  = , 
				}
				if .TargetArrowhead ==  && .SourceArrowhead ==  {
					 = append(, )
				}
			} else {
				 = append(, )
			}
		}

		if len() <= 1 {
			continue
		}
		 := .Points[0]
		 := .Points[len(.Points)-1]
		 := .X - .X
		 := .Y - .Y
		 := make([]*layoutgraph.Edge, 0, len()+1)
		 := make([]*layoutgraph.Edge, 0, len()+1)
		 = append(, )
		 = append(, )
		for ,  := range  {
			if  := .step();  != nil {
				return 
			}
			 = append(, [])
			 = append(, [])
		}

		if  := .reserveSort(len());  != nil {
			return 
		}
		if  := .reserveSort(len());  != nil {
			return 
		}
		if  >  {
			sort.Slice(, func(,  int) bool { return [].Points[0].X < [].Points[0].X })
			sort.Slice(, func(,  int) bool {
				,  := [], []
				return .Points[len(.Points)-1].X < .Points[len(.Points)-1].X
			})
		} else {
			sort.Slice(, func(,  int) bool { return [].Points[0].Y < [].Points[0].Y })
			sort.Slice(, func(,  int) bool {
				,  := [], []
				return .Points[len(.Points)-1].Y < .Points[len(.Points)-1].Y
			})
		}

		 := true
		for  := range  {
			if  := .step();  != nil {
				return 
			}
			if [] != [] {
				 = false
				break
			}
		}
		if ! {
			continue
		}
		 := -1
		for  := range  {
			if  := .step();  != nil {
				return 
			}
			if [] ==  {
				 = 
				break
			}
		}
		if  == 0 ||  == len()-1 {
			continue
		}
		 := [0]
		 := [len()-1]
		if .Label != nil && .Label != nil {
			continue
		}
		if  := .step();  != nil {
			return 
		}

		if .Label == nil {
			.Points, .Points = .Points, .Points
			if .From == .To {
				if  := reverseEdgeRouteGuarded(, );  != nil {
					return 
				}
				if  := reverseEdgeRouteGuarded(, );  != nil {
					return 
				}
			}
		} else if .Label == nil {
			.Points, .Points = .Points, .Points
			if .From == .To {
				if  := reverseEdgeRouteGuarded(, );  != nil {
					return 
				}
				if  := reverseEdgeRouteGuarded(, );  != nil {
					return 
				}
			}
		}
	}
	return .finish()
}

func reverseEdgeRouteGuarded( *layoutgraph.Edge,  *routeWorkGuard) error {
	for ,  := 0, len(.Points)-1;  < ; ,  = +1, -1 {
		if  := .step();  != nil {
			return 
		}
		.Points[], .Points[] = .Points[], .Points[]
	}
	return nil
}

func traceToShapeBorderGuarded( *layoutgraph.Edge,  *routeWorkGuard) ( error) {
	if  := .step();  != nil {
		return 
	}
	if  == nil || .From == nil || .To == nil || len(.Points) < 2 {
		return nil
	}
	 := snapshotPointer(.From.TopLeft)
	 := snapshotPointer(.To.TopLeft)
	defer func() {
		if  := recover();  != nil {
			.From.TopLeft = .restore()
			.To.TopLeft = .restore()
			panic()
		}
	}()
	traceToShapeBorder()
	return .step()
}