package layoutgraph

import (
	
	

	
	
	
)

type Sequence struct {
	Vessel         *Node
	Nodes          []*Node
	Graph          *Graph
	EdgeAbductions []*EdgeAbduction
	Container      *Node
}

// findAbductedNodeByEdge searches for the edge abduction related to the given edge and then returns the original node
func ( *Sequence) ( *Edge) *Node {
	for ,  := range .EdgeAbductions {
		if  != .Edge {
			continue
		}
		if .CurrentFrom == .Vessel {
			return .OriginallyFrom
		}
		if .CurrentTo == .Vessel {
			return .OriginallyTo
		}
	}
	return nil
}

// SyncGeometry resizes the sequence vessel and arranges its visible steps.
func ( *Sequence) () {
	if  := .SyncGeometryWithWork(unmeteredGroupGeometry);  != nil {
		panic()
	}
}

// SyncGeometryWithWork resizes the sequence vessel and arranges its visible
// steps through caller-owned cancellation and movement operations.
func ( *Sequence) ( SharedWorkStepper) error {
	if  == nil {
		return invariant.New("sequence geometry requires work accounting")
	}
	if  := .Step();  != nil {
		return 
	}
	if  == nil || .Vessel == nil {
		return invariant.New("sequence is missing its vessel")
	}
	if  := .resizeWithWork();  != nil {
		return 
	}
	return .arrangeStepsWithWork()
}

func ( *Sequence) ( workStepper) error {
	 := 0.0
	 := 0.0
	 := 0.0
	for ,  := range .Nodes {
		if  := .Step();  != nil {
			return 
		}
		if  == nil {
			return invariant.New("sequence contains a nil step")
		}
		 = math.Max(, +math.Max(0, .Width))
		 += SequenceAdvance(.Width)
		 = math.Max(, math.Max(0, .Height))
	}
	.Vessel.Width = 
	.Vessel.Height = 
	return nil
}

// ArrangeSteps places visible sequence steps relative to the vessel.
func ( *Sequence) () {
	if  := .arrangeStepsWithWork(unmeteredGroupGeometry);  != nil {
		panic()
	}
}

func ( *Sequence) ( workStepper) error {
	// hasn't been initialized yet
	if .Vessel.TopLeft == nil {
		return .Finish()
	}

	 := .Vessel.TopLeft.Copy()
	for ,  := range .Nodes {
		if  := .Step();  != nil {
			return 
		}
		.TopLeft = .Copy()
		.X += SequenceAdvance(.Width)
	}
	return .Finish()
}

// PlaceVessel positions the sequence vessel at the top-left of its steps.
func ( *Sequence) () {
	 := geo.NewPoint(math.Inf(1), math.Inf(1))
	for ,  := range .Nodes {
		if .TopLeft == nil {
			return
		}
		.X = math.Min(.X, .TopLeft.X)
		.Y = math.Min(.Y, .TopLeft.Y)
	}
	.Vessel.TopLeft = 
}

// SequenceAdvance is the horizontal distance from one step's top-left to
// the next. The rendered Step shape clamps its wedge to half of the width when
// the requested width is at most STEP_WEDGE_WIDTH, so fixed-size narrow steps
// must use the same geometry instead of always overlapping by the full wedge.
func ( float64) float64 {
	if  <= 0 {
		return 0
	}
	 := shape.STEP_WEDGE_WIDTH
	if  <=  {
		 =  / 2
	}
	return  - 
}

// SyncSequences synchronizes every active sequence in nested graph order.
func ( *Graph) () {
	if len(.Sequences) == 0 {
		return
	}

	 := func( *Node) {
		if ,  := .Sequences[];  {
			.SyncGeometry()
		}
	}
	for ,  := range .Nodes {
		.rdfsWalk()
	}
}

func ( *Sequence) () *Node {
	return .Nodes[0]
}
func ( *Sequence) () *Node {
	return .Nodes[len(.Nodes)-1]
}

// First and Last expose the endpoints needed by sequence-aware routing.
func ( *Sequence) () *Node { return .first() }
func ( *Sequence) () *Node  { return .last() }

func ( *Sequence) () bool {
	return  != nil && .Vessel.Graph != nil
}

func ( *Sequence) () string {
	 := []string{}
	for ,  := range .Nodes {
		 = append(, .DebugID())
	}
	return "[" + strings.Join(, ", ") + "]"
}