// Copyright (c) 2017 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 spore

import (
	

	
	basegraph 
)

const (
	fuzziness       = 0.0001
	doubleEpsilon   = 0.00001
	superWiggleRoom = 50.0
)

type vertex struct {
	point geometry.Point
}

type node struct {
	original *vertex
	vertex   geometry.Point
	rect     geometry.Rectangle
	origin   basegraph.NodeID
}

func newNode( *vertex,  geometry.Rectangle,  basegraph.NodeID) *node {
	return &node{original: , vertex: .point, rect: , origin: }
}

func ( *node) ( geometry.Point) {
	.vertex = .vertex.Add()
	.rect = .rect.Move()
}

func ( *node) ( geometry.Point) {
	.translate(.Sub(.vertex))
}

func ( *node) ( *node) float64 {
	 := math.Abs(.rect.Center().X - .rect.Center().X)
	 := math.Abs(.rect.Center().Y - .rect.Center().Y)
	,  := 0.0, 0.0
	,  := 1.0, 1.0
	if  > .rect.Width/2+.rect.Width/2 {
		 = math.Min(
			math.Abs(.rect.X-(.rect.X+.rect.Width)),
			math.Abs(.rect.X+.rect.Width-.rect.X),
		)
		 = 1 - /
	}
	if  > .rect.Height/2+.rect.Height/2 {
		 = math.Min(
			math.Abs(.rect.Y-(.rect.Y+.rect.Height)),
			math.Abs(.rect.Y+.rect.Height-.rect.Y),
		)
		 = 1 - /
	}
	 := math.Min(, )
	 := sporeVectorLength(geometry.Point{X: , Y: })
	 := 1 - 
	return float64( * )
}

func ( *node) ( *node,  geometry.Point) float64 {
	 := math.Inf(1)
	for ,  := range rectangleEdges(.rect) {
		for ,  := range rectangleEdges(.rect) {
			 = math.Min(, segmentDistance(.u, .v, .u, .v, ))
		}
	}
	return 
}

func ( *node) ( *node) bool {
	return fuzzyCompare(.rect.X, .rect.X+.rect.Width, fuzziness) <= 0 &&
		fuzzyCompare(.rect.X, .rect.X+.rect.Width, fuzziness) <= 0 &&
		fuzzyCompare(.rect.Y, .rect.Y+.rect.Height, fuzziness) <= 0 &&
		fuzzyCompare(.rect.Y, .rect.Y+.rect.Height, fuzziness) <= 0
}

type tEdge struct {
	u *vertex
	v *vertex
}

func sameEdge(,  *tEdge) bool {
	return .u == .u && .v == .v || .u == .v && .v == .u
}

type triangle struct {
	a, b, c *vertex
	edges   []*tEdge
	center  geometry.Point
}

func newTriangle(, ,  *vertex) *triangle {
	 := &triangle{a: , b: , c: }
	.edges = []*tEdge{{u: , v: }, {u: , v: }, {u: , v: }}
	 := .point.Sub(.point)
	 := .point.Sub(.point)
	 := .point.Sub(.point)
	 := .X*(.point.X+.point.X) + .Y*(.point.Y+.point.Y)
	 := .X*(.point.X+.point.X) + .Y*(.point.Y+.point.Y)
	 := 2 * (.X*.Y - .Y*.X)
	.center = geometry.Point{
		X: (.Y* - .Y*) / ,
		Y: (.X* - .X*) / ,
	}
	return 
}

func ( *triangle) ( *vertex) bool {
	return .a ==  || .b ==  || .c == 
}

func ( *triangle) ( *tEdge) bool {
	for ,  := range .edges {
		if sameEdge(, ) {
			return true
		}
	}
	return false
}

func ( *triangle) ( *vertex) bool {
	return fuzzyCompare(.center.Distance(.point), .center.Distance(.a.point), fuzziness) < 0
}

type tree struct {
	node     *node
	children []*tree
}

type sporeGraph struct {
	vertices         []*node
	edges            []*tEdge
	tree             *tree
	preferredRoot    *node
	treeConstruction string
	compaction       string
	cost             func(*tEdge) float64
	orthogonal       bool
}

func fuzzyCompare(, ,  float64) int {
	if  ==  || math.Abs(-) <=  || math.IsNaN() && math.IsNaN() {
		return 0
	}
	if  <  {
		return -1
	}
	return 1
}

func addEdge( []*tEdge,  *tEdge) []*tEdge {
	for ,  := range  {
		if sameEdge(, ) {
			return 
		}
	}
	return append(, )
}

func removeEdge( []*tEdge,  *tEdge) []*tEdge {
	for ,  := range  {
		if  ==  {
			return append([:], [+1:]...)
		}
	}
	return 
}