// Copyright (c) 2015 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 p4nodes

import (
	

	basegraph 
	
)

type Neighbor struct {
	Node layered.LNodeID
	Edge layered.LEdgeID
}

// NeighborhoodInformation caches the immutable neighbor relation used by all
// four Brandes-Koepf directional layouts. Arrays are indexed by the scratch
// IDs assigned in BuildNeighborhoodInformation.
type NeighborhoodInformation struct {
	NodeCount      int
	LayerIndex     []int
	NodeIndex      []int
	LeftNeighbors  [][]Neighbor
	RightNeighbors [][]Neighbor
}

func (
	 *layered.LGraphArena,
	 layered.LGraphID,
) *NeighborhoodInformation {
	 := append([]layered.LayerID(nil), .Graph().Layers...)
	 := 0
	for ,  := range  {
		 += len(.Layer().Nodes)
	}
	 := &NeighborhoodInformation{
		NodeCount:      ,
		LayerIndex:     make([]int, len()),
		NodeIndex:      make([]int, ),
		LeftNeighbors:  make([][]Neighbor, ),
		RightNeighbors: make([][]Neighbor, ),
	}
	 := 0
	for ,  := range  {
		.Layer().ID = 
		.LayerIndex[] = 
		for ,  := range .Layer().Nodes {
			.Node().ID = 
			.NodeIndex[] = 
			++
		}
	}
	for ,  := range  {
		for ,  := range .Layer().Nodes {
			 := .Node().ID
			.LeftNeighbors[] = .neighbors(, , true)
			.RightNeighbors[] = .neighbors(, , false)
		}
	}
	return 
}

func ( *NeighborhoodInformation) () {
	.LayerIndex = nil
	.NodeIndex = nil
	.LeftNeighbors = nil
	.RightNeighbors = nil
}

func ( *NeighborhoodInformation) (
	 *layered.LGraphArena,
	 layered.LNodeID,
	 bool,
) []Neighbor {
	 := make([]Neighbor, 0)
	 := 0
	 := .NodeOutgoingEdges()
	if  {
		 = .NodeIncomingEdges()
	}
	for ,  := range  {
		if .EdgeIsSelfLoop() || .EdgeIsInLayer() {
			continue
		}
		 := basegraph.Get(&.Edge().Properties, layered.PriorityStraightness)
		if  >  {
			 = 
			 = [:0]
		}
		if  ==  {
			 := .EdgeTargetNode()
			if  {
				 = .EdgeSourceNode()
			}
			 = append(, Neighbor{Node: , Edge: })
		}
	}
	sort.SliceStable(, func(,  int) bool {
		return .NodeIndex[.Node([].Node).ID] < .NodeIndex[.Node([].Node).ID]
	})
	return 
}