package d2isometricimg

import (
	
	
	
	

	
)

const (
	nativeBridgeMaxPoints = 350000
	nativeBridgeMaxWork   = 20000000
)

type nativeBridgeSegment struct {
	edge, part int
	a, b       Vec
	length     float64
	minX, maxX float64
	minZ, maxZ float64
}

type nativeBridgeCrossing struct {
	distance, clearance float64
	under               int
	underDistance       float64
}

type nativeBridgeSpan struct {
	first, last, half, height float64
}

type nativeBridgeWork struct {
	ctx       context.Context
	remaining int
}

func ( *nativeBridgeWork) ( int) error {
	if  := .ctx.Err();  != nil {
		return 
	}
	if  > .remaining {
		return fmt.Errorf("isometric crossing bridges exceed work limit")
	}
	.remaining -= 
	return nil
}

// nativeBridgeRoutes returns independent, rounded paths in the input edge order.
// Only true transverse intersections in straight, flat route interiors receive
// local bridges. Ports, curved corners, tangencies, and overlapping runs retain
// their original elevation. Edge IDs establish a stable lower-to-upper order.
// Callers use these same paths for solid/dashed tubes and animated packets.
func nativeBridgeRoutes( context.Context,  []d2isometric.Edge) ([][]Vec, error) {
	return nativeResolveBridgeRoutes(, , nativeBridgeMaxWork)
}

func nativeResolveBridgeRoutes( context.Context,  []d2isometric.Edge,  int) ([][]Vec, error) {
	if  == nil {
		return nil, fmt.Errorf("isometric crossing bridges require a context")
	}
	if len() > nativeBridgeMaxPoints {
		return nil, fmt.Errorf("isometric crossing bridges exceed edge limit")
	}
	 := nativeBridgeWork{ctx: , remaining: }
	if  := .spend(len());  != nil {
		return nil, 
	}
	 := make([][]Vec, len())
	 := make(map[string]bool, len())
	 := []nativeBridgeSegment{}
	 := make([][]int, len())
	 := 0
	for ,  := range  {
		if [.ID] {
			return nil, fmt.Errorf("isometric crossing bridges require unique edge IDs: %q", .ID)
		}
		[.ID] = true
		if len(.Points) > 10000 || len(.Points) > (nativeBridgeMaxPoints-)/8 {
			return nil, fmt.Errorf("isometric crossing bridges exceed route point limit")
		}
		if  := .spend(len(.Points));  != nil {
			return nil, 
		}
		for ,  := range .Points {
			if !bridgeFinite(.X) || !bridgeFinite(.Y) || !bridgeFinite(.Z) {
				return nil, fmt.Errorf("isometric crossing bridge route %q has invalid coordinates", .ID)
			}
		}
		[] = bridgeStraightRuns(nativeRoundedRoute(.Points))
		 += len([])
		[] = make([]int, max(0, len([])-1))
		for  := range [] {
			[][] = -1
		}
		if !bridgeVisible() {
			continue
		}
		for  := 1;  < len([]); ++ {
			,  := [][-1], [][]
			 := math.Hypot(.X-.X, .Z-.Z)
			if  < .42 || .Y != .Y {
				continue
			}
			[][-1] = len()
			 = append(, nativeBridgeSegment{,  - 1, , , , min(.X, .X), max(.X, .X), min(.Z, .Z), max(.Z, .Z)})
		}
	}
	// An X sweep discards disjoint ranges before exact intersection work. The
	// budget also covers adversarial sets whose ranges all overlap.
	 := make([]int, len())
	for  := range  {
		[] = 
	}
	sort.Slice(, func(,  int) bool {
		,  := [[]], [[]]
		if .minX != .minX {
			return .minX < .minX
		}
		if [.edge].ID != [.edge].ID {
			return [.edge].ID < [.edge].ID
		}
		return .part < .part
	})
	 := make([][]nativeBridgeCrossing, len())
	for ,  := range  {
		 := []
		for ,  := range [+1:] {
			if  := .spend(1);  != nil {
				return nil, 
			}
			 := []
			if .minX > .maxX {
				break
			}
			if .edge == .edge || .maxZ < .minZ || .maxZ < .minZ || .a.Y != .a.Y {
				continue
			}
			, ,  := bridgeIntersection(, )
			if ! {
				continue
			}
			, , ,  := , , , 
			if [.edge].ID < [.edge].ID {
				, , ,  = , , , 
			}
			 := nativeRouteRadius([.edge]) + nativeRouteRadius([.edge]) + .05
			 := max(.42, *3) / 2
			,  := [], []
			// Space beyond each ramp avoids altering a port's arrowhead or a
			// rounded corner. The lower path must also cross in its interior.
			if *.length < +.12 || (1-)*.length < +.12 || *.length < .12 || (1-)*.length < .12 {
				continue
			}
			[] = append([], nativeBridgeCrossing{ * .length, , ,  * .length})
		}
	}
	// Resolve lower paths first. Nearby crossings share one plateau instead of
	// repeatedly rising and falling. Multi-way crossings clear the lower bridge.
	sort.Slice(, func(,  int) bool {
		,  := [[]], [[]]
		if [.edge].ID != [.edge].ID {
			return [.edge].ID < [.edge].ID
		}
		return .part < .part
	})
	 := make([][]nativeBridgeSpan, len())
	for ,  := range  {
		if  := .spend(len([]) + 1);  != nil {
			return nil, 
		}
		 := []
		sort.Slice(, func(,  int) bool {
			if [].distance != [].distance {
				return [].distance < [].distance
			}
			return [[[].under].edge].ID < [[[].under].edge].ID
		})
		for ,  := range  {
			if  := .spend(len([.under]) + 1);  != nil {
				return nil, 
			}
			 := .clearance + bridgeHeight([.under], .underDistance)
			 := max(.42, *3) / 2
			if .distance- < .12 || .distance+ > [].length-.12 {
				continue
			}
			 := nativeBridgeSpan{.distance, .distance, , }
			 := []
			if len() > 0 && .first-.half <= [len()-1].last+[len()-1].half+.12 {
				 := [len()-1]
				.last = .last
				.height = max(.height, .height)
				.half = max(.half, .half)
				if .first-.half < .12 || .last+.half > [].length-.12 {
					continue
				}
				[len()-1] = 
			} else {
				 = append(, )
			}
			[] = 
		}
	}
	for ,  := range  {
		if len() < 2 {
			continue
		}
		 := make([]Vec, 0, len())
		 = append(, [0])
		for ,  := range [] {
			if  >= 0 {
				for ,  := range [] {
					if  := .spend(10);  != nil {
						return nil, 
					}
					if  > nativeBridgeMaxPoints-10 {
						return nil, fmt.Errorf("isometric crossing bridges exceed resolved point limit")
					}
					 += 10
					 := []
					 := func(,  float64) {
						 := nlerp(.a, .b, /.length)
						.Y = .a.Y + 
						 = append(, )
					}
					for  := 0;  <= 4; ++ {
						 := float64() / 4
						(.first-.half+*.half, .height*bridgeEase())
					}
					if .last != .first {
						(.last, .height)
					}
					for  := 1;  <= 4; ++ {
						 := float64() / 4
						(.last+*.half, .height*bridgeEase(1-))
					}
				}
			}
			 = append(, [+1])
		}
		[] = 
	}
	return , .Err()
}

func bridgeFinite( float64) bool { return !math.IsNaN() && !math.IsInf(, 0) && math.Abs() <= 1e9 }

func bridgeVisible( d2isometric.Edge) bool {
	return .Opacity > 0 && .StrokeWidth > 0 && (!.StrokeExplicit || nativePaint(.Stroke, "#657e9e").A > 0)
}

func bridgeStraightRuns( []Vec) []Vec {
	 := make([]Vec, 0, len())
	for ,  := range  {
		for len() >= 2 {
			,  := [len()-2], [len()-1]
			,  := nsub(, ), nsub(, )
			if ndot(, ) <= 0 || nlen(ncross(, )) > 1e-12*nlen()*nlen() {
				break
			}
			 = [:len()-1]
		}
		 = append(, )
	}
	return 
}

func bridgeIntersection(,  nativeBridgeSegment) (float64, float64, bool) {
	, , ,  := .b.X-.a.X, .b.Z-.a.Z, .b.X-.a.X, .b.Z-.a.Z
	 := * - *
	// A shallow crossing needs a long flyover to physically clear the lower
	// tube. This local treatment intentionally leaves those routes unchanged.
	if math.Abs() < .75*.length*.length {
		return 0, 0, false
	}
	,  := .a.X-.a.X, .a.Z-.a.Z
	,  := (*-*)/, (*-*)/
	return , ,  > 1e-8 &&  < 1-1e-8 &&  > 1e-8 &&  < 1-1e-8
}

func bridgeEase( float64) float64 { return .5 - .5*math.Cos(math.Pi*) }

// Interpolate the actual four-segment ramp, so a crossing over an earlier
// bridge clears the same geometry consumed by tubes and traffic packets.
func bridgeHeight( []nativeBridgeSpan,  float64) float64 {
	for ,  := range  {
		if  < .first-.half ||  > .last+.half {
			continue
		}
		 := min(1, min((-.first+.half)/.half, (.last+.half-)/.half))
		 := min(3, int(*4))
		 := *4 - float64()
		return .height * (bridgeEase(float64()/4)*(1-) + bridgeEase(float64(+1)/4)*)
	}
	return 0
}