package ui

import (
	"opslag.de/schobers/geom"
)

type StackPanel struct {
	ContainerBase
	Orientation Orientation
}

func BuildStackPanel(o Orientation, fn func(*StackPanel)) *StackPanel {
	var p = &StackPanel{Orientation: o}
	if fn != nil {
		fn(p)
	}
	return p
}

func (p *StackPanel) Arrange(ctx Context, bounds geom.RectangleF32, offset geom.PointF32, parent Control) {
	bounds = p.Orientation.FlipRect(bounds)
	var length float32
	var stretch int
	var desired = make([]geom.PointF32, len(p.Children))
	for i, child := range p.Children {
		var size = p.Orientation.FlipPt(child.DesiredSize(ctx, bounds.Size()))
		if geom.IsNaN32(size.Y) {
			stretch++
		} else {
			length += size.Y
		}
		desired[i] = size
	}
	var remainder = bounds.Dy() - length
	var childOffset float32
	for i, size := range desired {
		var height = size.Y
		if geom.IsNaN32(size.Y) {
			if remainder < 0 {
				height = 0
			} else {
				height = remainder / float32(stretch)
			}
		}
		var child = geom.RectF32(bounds.Min.X, bounds.Min.Y+childOffset, bounds.Max.X, bounds.Min.Y+childOffset+height)
		p.Children[i].Arrange(ctx, p.Orientation.FlipRect(child), offset, p)
		childOffset += height
	}
	p.ControlBase.Arrange(ctx, p.Orientation.FlipRect(bounds), offset, parent)
}

func (p *StackPanel) DesiredSize(ctx Context, size geom.PointF32) geom.PointF32 {
	var length float32
	var width float32
	for _, child := range p.Children {
		var size = child.DesiredSize(ctx, size)
		var l, w = p.Orientation.LengthParallel(size), p.Orientation.LengthPerpendicular(size)
		if geom.IsNaN32(l) {
			length = l
		} else {
			if !geom.IsNaN32(length) {
				length += l
			}
		}

		if geom.IsNaN32(w) {
			width = w
		} else {
			if !geom.IsNaN32(width) {
				width = geom.Max32(width, w)
			}
		}
	}
	return p.Orientation.Pt(length, width)
}

func (p *StackPanel) Render(ctx Context) {
	p.RenderBackground(ctx)
	var bounds = p.Bounds()
	for _, child := range p.Children {
		var childB = child.Bounds()
		if childB.Min.X >= bounds.Max.X || childB.Min.Y >= bounds.Max.Y || childB.Max.X < bounds.Min.X || childB.Max.Y < bounds.Min.Y || childB.Max.X < 0 || childB.Max.Y < 0 {
			continue
		}
		child.Render(ctx)
	}
}