package placement

import (
	

	
	
	
)

// occupied reports whether point is the top-left position of a graph node.
func occupied( *layoutgraph.Graph,  *geo.Point) (*layoutgraph.Node, bool) {
	for ,  := range .Nodes {
		if .TopLeft != nil &&  != nil && *.TopLeft == * {
			return , true
		}
	}
	return nil, false
}

// withinMaxSize reports whether the graph fits inside the supported placement
// bounds.
func withinMaxSize( *layoutgraph.Graph) bool {
	,  := .BoundingBox()
	 := .X - .X
	 := .Y - .Y
	return  <= limits.MaxGraphSize &&  <= limits.MaxGraphSize
}

// intersectsOtherNode reports whether the center-to-center segment crosses an
// unrelated graph node.
func intersectsOtherNode( *layoutgraph.Graph, ,  *layoutgraph.Node) bool {
	 := .Center()
	 := .Center()
	for ,  := range .Nodes {
		if  ==  ||  ==  {
			continue
		}
		if .IsDescendantOf() || .IsDescendantOf() {
			continue
		}
		if .IsDescendantOf() || .IsDescendantOf() {
			continue
		}
		if .PassesThrough(, ) {
			return true
		}
	}
	return false
}

func median( layoutgraph.Nodes,  bool) (float64, float64) {
	 := append(layoutgraph.Nodes(nil), ...)
	 := append(layoutgraph.Nodes(nil), ...)
	sort.Slice(, func(,  int) bool {
		,  := [], []
		,  := .TopLeft.X, .TopLeft.X
		if  {
			 += .Width / 2
			 += .Width / 2
		}
		if  ==  {
			return .ID < .ID
		}
		return  < 
	})
	sort.Slice(, func(,  int) bool {
		,  := [], []
		,  := .TopLeft.Y, .TopLeft.Y
		if  {
			 += .Height / 2
			 += .Height / 2
		}
		if  ==  {
			return .ID < .ID
		}
		return  < 
	})

	 := len() / 2
	if  {
		 := [].TopLeft.X + [].Width/2
		 := [].TopLeft.Y + [].Height/2
		if len()%2 == 0 {
			 = ( + [-1].TopLeft.X + [-1].Width/2) / 2
			 = ( + [-1].TopLeft.Y + [-1].Height/2) / 2
		}
		return  / [0].Graph.CellSize,  / [0].Graph.CellSize
	}
	 := [].TopLeft.X + 0.5
	 := [].TopLeft.Y + 0.5
	if len()%2 == 0 {
		 = ( + [-1].TopLeft.X) / 2
		 = ( + [-1].TopLeft.Y) / 2
	}
	return , 
}

// medianToNeighbors approximates the two-dimensional geometric median of a
// node's currently positioned placement neighbors.
func medianToNeighbors( *layoutgraph.Node,  bool,  []*layoutgraph.EdgeAbduction) (float64, float64) {
	return median(adjacents(, ), )
}

func adjacents( *layoutgraph.Node,  []*layoutgraph.EdgeAbduction) []*layoutgraph.Node {
	 := make([]*layoutgraph.Node, 0, len(.Edges))
	 := borrowEdgeAbductionBools(len())
	defer returnEdgeAbductionBools()
	 := .values
	for ,  := range .Edges {
		 := .Adjacent()
		if .TopLeft == nil {
			continue
		}
		 := 
		for ,  := range  {
			if [] {
				continue
			}
			if .CurrentFrom ==  && .CurrentTo ==  && .OriginallyTo != nil {
				[],  = true, .OriginallyTo
				break
			}
			if .CurrentFrom ==  && .CurrentTo ==  && .OriginallyFrom != nil {
				[],  = true, .OriginallyFrom
				break
			}
		}
		 = append(, )
	}
	if len() != 0 {
		return 
	}

	for ,  := range .OrderedNears() {
		if .Cluster.IsActive() {
			 = .Cluster.Vessel
		} else if .Sequence.IsActive() {
			 = .Sequence.Vessel
		}
		if ,  := .Graph.NodeToTree[];  {
			for .Parent != nil {
				 = .Parent
			}
			 = .SentinelNode()
		}
		if .TopLeft != nil && .IsDescendantOf(.Container) {
			 = append(, )
		}
	}
	if len() != 0 {
		return 
	}

	var  []*layoutgraph.Node
	if .IsClusterVessel() {
		for ,  := range .Graph.Clusters[].Nodes {
			 = append(, .OrderedNears()...)
		}
	}
	if  := .Graph.Sequences[];  != nil {
		for ,  := range .Nodes {
			 = append(, .OrderedNears()...)
		}
	}
	for ,  := range .Graph.Trees[] {
		 := []*layoutgraph.Tree{}
		for len() > 0 {
			 := [0]
			 = [1:]
			 = append(, .Node.OrderedNears()...)
			 = append(, .Children...)
		}
	}
	for ,  := range  {
		 := 
		if .Cluster.IsActive() {
			 = .Cluster.Vessel
		} else if .Sequence.IsActive() {
			 = .Sequence.Vessel
		}
		if ,  := .Graph.NodeToTree[];  {
			for .Parent != nil {
				 = .Parent
			}
			 = .SentinelNode()
		}
		if .TopLeft != nil {
			 = append(, )
		}
	}
	return 
}