// Copyright (c) 2016 Kiel University and others.
// Copyright (c) 2026 The elk-go Authors.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0.
//
// SPDX-License-Identifier: EPL-2.0

package wrapping

import (
	

	basegraph 
	
)

// WrapSingleEdgeGraph is the direct SingleEdgeGraphWrapper port. It applies
// only after layering and crossing minimization, immediately before node
// placement.
func ( *layered.LGraphArena,  layered.LGraphID) {
	 := .Graph()
	if len(.Layers) == 0 {
		return
	}
	 := NewGraphStats(, )
	 := .MaxWidth() * float64(.LongestPath)
	 :=  / .MaxWidth()
	if .DesiredAspectRatio >  {
		return
	}

	var  cutIndexCalculator
	switch basegraph.Get(&.Properties, layered.WrappingCuttingStrategy) {
	case layered.CuttingManual:
		 = manualCutIndexCalculator{}
	case layered.CuttingARD:
		 = ardCutIndexHeuristic{}
	default:
		 = msdCutIndexHeuristic{}
	}
	 := .cutIndexes(, , )
	if !.guaranteesValid() {
		switch basegraph.Get(&.Properties, layered.WrappingValidifyStrategy) {
		case layered.ValidifyLookBack:
			 = ValidifyIndexesLookingBack(, )
		case layered.ValidifyGreedy:
			 = ValidifyIndexesGreedily(, )
		}
	}
	performCuts(, , , )
}

func ( *GraphStats,  []int) []int {
	 := make([]int, 0, len())
	 := 0
	for ,  := range  {
		 :=  + 
		for  < .LongestPath && !.IsCutAllowed() {
			++
			++
		}
		if  >= .LongestPath {
			break
		}
		 = append(, )
	}
	return 
}

func ( *GraphStats,  []int) []int {
	if len() == 0 {
		return nil
	}
	 := []int{math.MinInt32}
	for  := 1;  < .LongestPath; ++ {
		if .IsCutAllowed() {
			 = append(, )
		}
	}
	if len() == 1 {
		return nil
	}
	 = append(, math.MaxInt32)
	return validifyIndexesLookingBack(, )
}

func validifyIndexesLookingBack(,  []int) []int {
	 := make([]int, 0, len())
	, ,  := 0, 0, 0
	for  < len()-1 &&  < len() {
		 := [] + 
		for [+1] <  {
			++
		}
		 := 0
		 :=  - []
		 := [+1] - 
		if  >  {
			++
		}
		 := [+]
		 = append(, )
		 +=  - 
		++
		for  < len() && []+ <=  {
			++
		}
		 += 1 + 
	}
	return 
}

func performCuts(
	 *layered.LGraphArena,
	 layered.LGraphID,
	 *GraphStats,
	 []int,
) {
	if len() == 0 {
		return
	}
	 := .Graph()
	, ,  := 0, 0, 0
	 := [0]
	for  < .LongestPath {
		if  ==  {
			 = 0
			++
			if  < len() {
				 = []
			} else {
				 = .LongestPath + 1
			}
		}
		if  !=  {
			 := .Layers[]
			 := .Layers[]
			 := append([]layered.LNodeID(nil), .Layer().Nodes...)
			for ,  := range  {
				.SetNodeLayerAt(, &, len(.Layer().Nodes))
				if  == 0 {
					 := append([]layered.LEdgeID(nil), .NodeIncomingEdges()...)
					for ,  := range  {
						.ReverseEdge(, , true)
						basegraph.Set(&.Properties, layered.Cyclic, true)
						InsertDummies(, , , 1)
					}
				}
			}
		}
		++
		++
	}
	 := .Layers[:0]
	for ,  := range .Layers {
		if len(.Layer().Nodes) > 0 {
			 = append(, )
		}
	}
	.Layers = 
}