package quality

import (
	
	
	
	
	
)

type positionedLabel struct {
	box  geo.Box
	node *layoutgraph.Node
	edge *layoutgraph.Edge
}

// measureLabels treats all rendered label and icon boxes consistently, including
// loop and arrowhead labels. Padding-only near misses do not trigger repair.
func measureLabels( *layoutgraph.Graph,  *Metrics,  *limits.WorkGuard) error {
	if  := .Step();  != nil {
		return 
	}
	var  []positionedLabel
	 := func( geo.Box,  *layoutgraph.Node,  *layoutgraph.Edge) {
		if .Width > 0 && .Height > 0 {
			 = append(, positionedLabel{, , })
		}
	}
	for ,  := range .Nodes {
		if  := .Step();  != nil {
			return 
		}
		if .IsInvisible {
			continue
		}
		if .Label != nil && .Label.Position != label.Unset {
			if .Label.Position.IsOutside() {
				if  := chargeEvaluationWork(, 4*len(.Nodes));  != nil {
					return 
				}
			}
			(geo.Box{TopLeft: .LabelTopLeft(.Label.Position, .Label.Width, .Label.Height), Width: .Label.Width, Height: .Label.Height}, , nil)
		}
		if .Icon != nil && !.IsImage() {
			if .Icon.Position.IsOutside() {
				if  := chargeEvaluationWork(, 4*len(.Nodes));  != nil {
					return 
				}
			}
			 := .IconSize(.Icon.Position)
			(geo.Box{TopLeft: .LabelTopLeft(.Icon.Position, , ), Width: , Height: }, , nil)
		}
	}
	 := make([]*layoutgraph.Edge, 0, len(.Edges))
	for ,  := range .Edges {
		if  := .Step();  != nil {
			return 
		}
		if .IsInvisible {
			continue
		}
		 = append(, )
		if len(.Points) < 2 {
			continue
		}
		if .Label != nil && .Label.Position != label.Unset {
			if  := chargeEvaluationWork(, len(.Points));  != nil {
				return 
			}
			(labelBox(), nil, )
		}
		if .SourceArrowheadLabel != nil {
			if  := chargeEvaluationWork(, len(.Points));  != nil {
				return 
			}
			(labeling.PositionArrowheadLabel(, false, .Points).Box, nil, )
		}
		if .TargetArrowheadLabel != nil {
			if  := chargeEvaluationWork(, len(.Points));  != nil {
				return 
			}
			(labeling.PositionArrowheadLabel(, true, .Points).Box, nil, )
		}
	}
	for ,  := range  {
		if  := .Step();  != nil {
			return 
		}
		for ,  := range [:] {
			if  := .Step();  != nil {
				return 
			}
			if boxesOverlapWithPadding(.box, .box, 0) {
				.TextOcclusions++
			}
		}
		for ,  := range .Nodes {
			if  := .Step();  != nil {
				return 
			}
			if .IsInvisible || !.IsRectangular() {
				continue
			}
			if !boxesOverlapWithPadding(.box, .Box, 0) {
				continue
			}
			 := false
			var  error
			if .node != nil {
				,  = evaluationIsDescendantOf(.node, , )
			} else {
				,  = endpointAncestor(.edge, , )
				// Labels may be inside enclosing containers, but must remain
				// outside the shapes to which their edge connects.
				 =  &&  != .edge.From &&  != .edge.To
			}
			if  != nil {
				return 
			}
			if  && boxCovers(.Box, .box) {
				continue
			}
			.TextOcclusions++
		}
		for ,  := range  {
			if  := .Step();  != nil {
				return 
			}
			if  == .edge || .IsCurve {
				continue
			}
			 := false
			for  := 1;  < len(.Points); ++ {
				if  := .Step();  != nil {
					return 
				}
				if segmentEntersBox(.box, .Points[-1], .Points[]) {
					 = true
					break
				}
			}
			if  {
				.TextOcclusions++
			}
		}

	}
	return nil
}