// Copyright (c) 2015, 2020 Kiel University and others.
//
// 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 layered

import (
	

	
	basegraph 
	
)

const minimumEdgeSpacing = 2.0

// ConfigureGraphProperties applies GraphConfigurator's non-pipeline setup.
func ( *LGraphArena,  LGraphID) {
	 := .Graph()
	if  := basegraph.Get(&.Properties, SpacingEdgeEdge);  < minimumEdgeSpacing {
		basegraph.Set(&.Properties, SpacingEdgeEdge, minimumEdgeSpacing)
	}
	if basegraph.Get(&.Properties, DirectionOption) == DirectionUndefined {
		// LGraphUtil.getDirection derives this from interactive coordinates.
		// With no usable coordinates it returns RIGHT, which is the common and
		// D2-active path.
		basegraph.Set(&.Properties, DirectionOption, DirectionRight)
	}
	 := basegraph.Get(&.Properties, RandomSeed)
	if  == 0 {
		basegraph.Set(&.Properties, Random, javacompat.NewRandom(time.Now().UnixNano()))
	} else {
		basegraph.Set(&.Properties, Random, javacompat.NewRandom(int64()))
	}
	if ,  := basegraph.TryGet(&.Properties, FavorStraightEdges); ! {
		basegraph.Set(&.Properties, FavorStraightEdges,
			basegraph.Get(&.Properties, EdgeRoutingOption) == EdgeRoutingOrthogonal)
	}
	copyOriginalPortConstraints(, )
}

func copyOriginalPortConstraints( *LGraphArena,  LGraphID) {
	for ,  := range .GraphAllNodes() {
		 := basegraph.Get(&.Node().Properties, PortConstraintsOption)
		basegraph.Set(&.Node().Properties, OriginalPortConstraints, )
		if .Node().NestedGraph != nil {
			(, *.Node().NestedGraph)
		}
	}
}

func ( *LGraphArena,  LGraphID) PipelineConfiguration {
	ConfigureGraphProperties(, )
	 := .Graph()
	 := PipelineConfiguration{Phases: PhaseStrategies{
		CycleBreaking:        basegraph.Get(&.Properties, CycleBreaking),
		Layering:             basegraph.Get(&.Properties, Layering),
		CrossingMinimization: basegraph.Get(&.Properties, CrossingMinimization),
		NodePlacement:        basegraph.Get(&.Properties, NodePlacement),
		EdgeRouting:          basegraph.Get(&.Properties, EdgeRoutingOption),
	}}

	.Intermediates.
		AddBefore(PhaseNodePlacement, InnermostNodeMarginCalculator).
		AddBefore(PhaseNodePlacement, LabelAndNodeSizeProcessor).
		AddBefore(PhaseEdgeRouting, LayerSizeAndGraphHeightCalculator).
		AddAfter(PhaseEdgeRouting, EndLabelSorter)

	if basegraph.Get(&.Properties, Hierarchy) == HierarchyIncludeChildren {
		.Intermediates.AddAfter(PhaseEdgeRouting, HierarchicalNodeResizer)
	}
	if basegraph.Get(&.Properties, FeedbackEdges) {
		.Intermediates.AddBefore(PhaseCycleBreaking, PortSideProcessor)
	} else {
		.Intermediates.AddBefore(PhaseNodeOrdering, PortSideProcessor)
	}
	switch basegraph.Get(&.Properties, DirectionOption) {
	case DirectionLeft, DirectionDown, DirectionUp:
		.Intermediates.
			AddBefore(PhaseCycleBreaking, DirectionPreprocessor).
			AddAfter(PhaseEdgeRouting, DirectionPostprocessor)
	}
	if basegraph.Get(&.Properties, ConsiderModelOrder) != OrderingNone {
		.Intermediates.AddBefore(PhaseNodeOrdering, SortByInputOrderOfModel)
	}
	if basegraph.Get(&.Properties, NodePromotionStrategyOption) != NodePromotionNone {
		.Intermediates.AddBefore(PhaseNodeOrdering, NodePromotion)
	}
	if basegraph.Get(&.Properties, PostCompactionStrategy) != GraphCompactionNone &&
		basegraph.Get(&.Properties, EdgeRoutingOption) != EdgeRoutingPolyline {
		.Intermediates.AddAfter(PhaseEdgeRouting, HorizontalCompactor)
	}
	if basegraph.Get(&.Properties, HighDegreeNodeTreatment) {
		.Intermediates.AddBefore(PhaseNodeOrdering, HighDegreeNodeLayerProcessor)
	}
	if basegraph.Get(&.Properties, SemiInteractive) {
		.Intermediates.AddBefore(PhaseNodeOrdering, SemiInteractiveCrossMinProcessor)
	}
	if basegraph.Get(&.Properties, LayerUnzippingStrategyOption) == LayerUnzippingAlternating {
		.Intermediates.AddBefore(PhaseNodePlacement, AlternatingLayerUnzipper)
	}
	// GraphConfigurator evaluates this while the nodes are still layerless.
	// NodeFlexibility.NONE is an enum value rather than Java null, so every
	// node satisfies the source's non-null predicate when the recomputation
	// option is explicitly present.
	if len(.LayerlessNodes) != 0 &&
		basegraph.Has(&.Properties, NetworkSimplexRecomputeNodePlacement) {
		.Intermediates.AddAfter(PhaseNodePlacement, NodePlacementRepeater)
	}
	if basegraph.Get(&.Properties, GraphProperties)&GraphPropertyPartitions != 0 {
		.Intermediates.
			AddBefore(PhaseCycleBreaking, PartitionPreprocessor).
			AddBefore(PhaseLayering, PartitionMidprocessor).
			AddBefore(PhaseNodeOrdering, PartitionPostprocessor)
	}
	if basegraph.Get(&.Properties, GraphProperties)&GraphPropertyComments != 0 {
		.Intermediates.
			AddBefore(PhaseCycleBreaking, CommentPreprocessor).
			AddBefore(PhaseNodePlacement, CommentNodeMarginCalculator).
			AddAfter(PhaseEdgeRouting, CommentPostprocessor)
	}
	if basegraph.Get(&.Properties, core.InteractiveLayout) ||
		basegraph.Get(&.Properties, GeneratePositionAndLayerIDs) {
		.Intermediates.AddAfter(PhaseEdgeRouting, ConstraintsPostprocessor)
	}
	switch basegraph.Get(&.Properties, WrappingStrategyOption) {
	case WrappingSingleEdge:
		.Intermediates.AddBefore(PhaseNodePlacement, SingleEdgeGraphWrapper)
	case WrappingMultiEdge:
		.Intermediates.
			AddBefore(PhaseNodeOrdering, BreakingPointInserter).
			AddBefore(PhaseNodePlacement, BreakingPointProcessor).
			AddAfter(PhaseEdgeRouting, BreakingPointRemover)
	}
	return 
}

func () ProcessorConfiguration {
	var  ProcessorConfiguration
	.AddAfter(PhaseEdgeRouting, ReversedEdgeRestorer)
	return 
}

func () ProcessorConfiguration {
	var  ProcessorConfiguration
	.
		AddBefore(PhaseCycleBreaking, EdgeAndLayerConstraintEdgeReverser).
		AddBefore(PhaseLayering, LayerConstraintPreprocessor).
		AddBefore(PhaseNodeOrdering, LayerConstraintPostprocessor)
	return 
}