// Copyright (c) 2021 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 p1cycles

import (
	basegraph 
	
)

// ModelOrderCycleBreaker reverses edges that run against the imported model
// order, including ELK's offsets for first/last layer constraints.
type ModelOrderCycleBreaker struct {
	firstSeparateModelOrder int
	lastSeparateModelOrder  int
}

func (*ModelOrderCycleBreaker) (
	 *layered.LGraphArena,
	 layered.LGraphID,
) layered.ProcessorConfiguration {
	return layered.GreedyCycleConfiguration()
}

func ( *ModelOrderCycleBreaker) ( *layered.LGraphArena,  layered.LGraphID) error {
	.firstSeparateModelOrder = 0
	.lastSeparateModelOrder = 0
	 := .Graph().LayerlessNodes
	 := len()
	for ,  := range  {
		if ,  := basegraph.TryGet(&.Node().Properties, layered.ModelOrder);  && +1 >  {
			 =  + 1
		}
	}

	 := make([]layered.LEdgeID, 0)
	for ,  := range  {
		 := .constraintModelOrder(, , )
		for ,  := range .NodeOutgoingEdges() {
			 := .EdgeTargetNode()
			if .constraintModelOrder(, , ) <  {
				 = append(, )
			}
		}
	}
	for ,  := range  {
		.ReverseEdge(, , true)
		basegraph.Set(&.Graph().Properties, layered.Cyclic, true)
	}
	return nil
}

func ( *ModelOrderCycleBreaker) (
	 *layered.LGraphArena,
	 layered.LNodeID,
	 int,
) int {
	 := .Node()
	 := 0
	switch basegraph.Get(&.Properties, layered.LayerConstraintOption) {
	case layered.LayerConstraintFirstSeparate:
		 = -2* + .firstSeparateModelOrder
		.firstSeparateModelOrder++
	case layered.LayerConstraintFirst:
		 = -
	case layered.LayerConstraintLast:
		 = 
	case layered.LayerConstraintLastSeparate:
		 = 2* + .lastSeparateModelOrder
		.lastSeparateModelOrder++
	}
	if ,  := basegraph.TryGet(&.Properties, layered.ModelOrder);  {
		 += 
	}
	return 
}