package d2isometricimg

import (
	
	

	
	
	
	
	
)

const (
	nativeSequenceLifelineY = .10
	nativeSequenceMessageY  = .30
)

func nativeSequenceEdge( d2isometric.Edge) bool {
	return .SequenceRole == "lifeline" || .SequenceRole == "message"
}

func nativeSequenceEdgeY( d2isometric.Edge) float64 {
	if .SequenceRole == "lifeline" {
		return nativeSequenceLifelineY
	}
	return nativeSequenceMessageY
}

// Sequence edges never enter dependency routing. Partitioning before those
// passes also prevents messages from adding bridges or lanes to ordinary
// connections in a mixed scene. All input slices remain source-owned.
func nativeEdgeRoutes( context.Context,  []d2isometric.Edge,  []d2isometric.Node,  []d2isometric.Board,  ...map[string]float64) (,  [][]Vec,  error) {
	if  == nil {
		return nil, nil, fmt.Errorf("isometric routes require a context")
	}
	,  = make([][]Vec, len()), make([][]Vec, len())
	var  []d2isometric.Edge
	var  []int
	 := 0
	for ,  := range  {
		if  := .Err();  != nil {
			return nil, nil, 
		}
		if len(.Points) > 10000 ||  > nativeBridgeMaxPoints-len(.Points) {
			return nil, nil, fmt.Errorf("isometric routes exceed point budget")
		}
		 += len(.Points)
		if !nativeSequenceEdge() {
			,  = append(, ), append(, )
			continue
		}
		 := append([]Vec(nil), .Points...)
		for  := range  {
			if !captionFinite([].X, [].Y, [].Z) {
				return nil, nil, fmt.Errorf("isometric sequence route %q has invalid coordinates", .ID)
			}
			[].Y = nativeSequenceEdgeY()
		}
		[], [] = , 
	}
	,  := nativeLaneRoutes(, , , )
	if  != nil {
		return nil, nil, 
	}
	 := append([]d2isometric.Edge(nil), ...)
	for  := range  {
		[].Points = []
	}
	,  := nativeBridgeRoutes(, )
	if  != nil {
		return nil, nil, 
	}
	,  = nativeSolidContactRoutes(, , , , ...)
	if  != nil {
		return nil, nil, 
	}
	for ,  := range  {
		[], [] = [], []
	}
	return , , nil
}

func nativeSequenceTint( d2isometric.Edge) string {
	if .StrokeExplicit {
		return .Stroke
	}
	return "#263c4e"
}

// Use the native 2D caption API, including its self-loop and endpoint rules.
// Compiled text remains aligned with the source X axis on the flat surface;
// route direction does not rotate or reposition that text.
type nativeSequenceCaption struct {
	style   d2target.Text
	surface labelSurface
	main    bool
}

func nativeSequenceCaptionData( d2isometric.Edge,  float64) ([]nativeSequenceCaption, labelSurface) {
	if  <= 0 || !captionFinite() || len(.Points) < 2 {
		return nil, labelSurface{}
	}
	 := .Metadata.Original
	,  := 0., 0.
	if len(.Route) >= 2 && .Route[0] != nil {
		,  = .Points[0].X-.Route[0].X*, .Points[0].Z-.Route[0].Y*
	} else {
		.Route = make([]*geo.Point, len(.Points))
		for ,  := range .Points {
			.Route[] = geo.NewPoint(.X/, .Z/)
		}
	}
	for ,  := range .Route {
		if  == nil || !captionFinite(.X, .Y) {
			return nil, labelSurface{}
		}
	}
	if label.FromString(.LabelPosition) == label.Unset {
		.LabelPosition = label.InsideMiddleCenter.String()
	}
	if label.FromString(.IconPosition) == label.Unset {
		.IconPosition = label.InsideMiddleCenter.String()
	}
	 := func( *geo.Point, ,  int) labelSurface {
		if  == nil || !captionFinite(.X, .Y) {
			return labelSurface{}
		}
		return labelSurface{center: nv(+(.X+float64()/2)*, nativeSequenceEdgeY()+.006, +(.Y+float64()/2)*), width: float64(max(1, )) * , depth: float64(max(1, )) * }
	}
	var  []nativeSequenceCaption
	if .Label != "" {
		 := .Text
		.Label = .Label
		 = append(, nativeSequenceCaption{, (.GetLabelTopLeft(), .LabelWidth, .LabelHeight), true})
	}
	for ,  := range []struct {
		 *d2target.Text
		  bool
	}{{.SourceLabel, false}, {.TargetLabel, true}} {
		if . == nil || ..Label == "" {
			continue
		}
		if . {
			.DstLabel = .
		} else {
			.SrcLabel = .
		}
		 := *.
		// Native D2 endpoint captions use the main connection's font size
		// and the primary italic face, independently of a rich main label.
		.FontSize, .FontFamily, .Bold, .Italic, .Underline = .FontSize, "default", false, true, false
		 = append(, nativeSequenceCaption{, (.GetArrowheadLabelPosition(.), .LabelWidth, .LabelHeight), false})
	}
	var  labelSurface
	if .Icon != nil {
		 = (.GetIconPosition(), d2target.DEFAULT_ICON_SIZE, d2target.DEFAULT_ICON_SIZE)
	}
	return , 
}

func ( *meshBuilder) ( d2isometric.Edge,  []Vec,  *routeCaptionPlacer) {
	if .StrokeWidth > 0 {
		.AvoidRoute(, float64(.StrokeWidth)*.scale/2)
	}
	,  := nativeSequenceCaptionData(, .scale)
	for ,  := range  {
		.reserve(captionRect(.surface, true))
	}
	if .width > 0 && .depth > 0 {
		.reserve(captionRect(, true))
	}
}

func ( *meshBuilder) ( d2isometric.Edge,  []Vec,  *d2isometric.Scene) []packetRoute {
	if len() < 2 || .Opacity <= 0 {
		return nil
	}
	 := nativeSequenceTint()
	 := nativeMaterial(, 1, 0, .Opacity)
	.Unlit = true
	 := float64(.StrokeWidth) * .scale / 2
	 := routeLengths()
	 := [len()-1]
	 := len(.triangles)
	if  > 0 &&  > 0 {
		 := 
		,  := nativeArrowClearance(.SourceArrow, .StrokeWidth)/, 1-nativeArrowClearance(.TargetArrow, .StrokeWidth)/
		if  > 0 ||  < 1 {
			 = nativeRouteSection(, , , )
		}
		 := .StrokeDash
		if  <= 0 {
			.routeInk(, , )
		} else {
			 := routeLengths()
			if len() > 1 {
				 := [len()-1]
				,  := svg.GetStrokeDashAttributes(float64(.StrokeWidth), )
				,  = *.scale, *.scale
				if !captionFinite(, ) ||  <= 0 ||  <= 0 {
					,  = float64(.StrokeWidth)**.scale, float64(.StrokeWidth)**.scale
				}
				if !captionFinite(, ) ||  <= 0 ||  <= 0 || /(+) > 50000 {
					.err = fmt.Errorf("isometric sequence dashes exceed geometry budget")
					return nil
				}
				for  := 0.;  < ;  +=  +  {
					.routeInk(nativeRouteSection(, , /, min(1, (+)/)), , )
					if .err != nil {
						return nil
					}
				}
			}
		}
	}
	,  := nativeSequenceCaptionData(, .scale)
	if nativeCaptionOnEdge(.Metadata.Original) {
		for ,  := range  {
			if .main {
				.routeCaptionKnockout(, .surface)
				break
			}
		}
	}
	 := len(.triangles)
	.arrowWithOpacity(string(.SourceArrow), [0], nsub([0], [1]), , .StrokeWidth, .Opacity)
	.arrowWithOpacity(string(.TargetArrow), [len()-1], nsub([len()-1], [len()-2]), , .StrokeWidth, .Opacity)
	for  := ;  < len(.triangles); ++ {
		for  := range .triangles[].V {
			.triangles[].V[].Position.Y = nativeSequenceEdgeY()
			.triangles[].V[].Normal = nv(0, 1, 0)
		}
	}
	.addMeshLink(.Link, .Tooltip, .triangles[:])
	 := nativeCaptionPaint()
	for ,  := range  {
		 := (.style.Color)
		if nativeToken(.style.Color) {
			// Match the classic wire/outline ink. The default source caption
			// gray loses contrast on physical container plates.
			 = "#263c4e"
		}
		if .main && .FontExplicit {
			 = .FontColor
		}
		if .main && .Metadata.Original.Fill != "" {
			.style.LabelFill = .Metadata.Original.Fill
		}
		.style.LabelFill = (.style.LabelFill)
		if .main {
			.addSurfaceLink(.Link, .Tooltip, .surface)
		}
		.label(.style.Label, .surface, .style, , .Opacity, "edge")
	}
	if .width > 0 && .depth > 0 {
		.shapeIcon(d2target.Shape{ID: .ID, Icon: .Metadata.Original.Icon}, , .Opacity, "edge", .Metadata.Original.IconBorderRadius)
		.addSurfaceLink(.Link, .Tooltip, )
	}
	if .Metadata.Original.Animated && .StrokeWidth > 0 && .Color.A > 0 {
		 := nativeMaterial("#e9f8ff", .2, .15, float64(.Color.A)/255)
		.Emissive = nativePaint(, "#263c4e")
		,  := .TargetArrow != "" && .TargetArrow != "none", .SourceArrow != "" && .SourceArrow != "none"
		if ! && ! {
			 = true
		}
		return []packetRoute{{points: , lengths: , material: , forward: , reverse: }}
	}
	return nil
}