package ui

import (
	"math"
	"strings"
)

// renderScope draws a Lissajous-style XY oscilloscope using Braille dots.
// Since the audio tap is mono, a phase-delayed copy of the signal is used as
// the Y axis. The delay slowly oscillates over time, producing continuously
// evolving Lissajous figures — circles for pure tones, complex knots for music.
func (v *Visualizer) renderScope() string {
	height := v.Rows
	dotRows := height * 4
	dotCols := PanelWidth * 2

	samples := v.waveBuf
	n := len(samples)

	grid := make([]bool, dotRows*dotCols)

	if n > 1 {
		// Phase delay slowly oscillates for evolving Lissajous patterns.
		baseDelay := n / 4
		wobble := int(math.Sin(float64(v.frame)*0.02) * float64(n/8))
		delay := max(1, min(n-1, baseDelay+wobble))

		// Plot ~512 XY pairs for a dense, smooth figure.
		plotPoints := min(n-delay, 512)
		step := max(1, (n-delay)/plotPoints)

		var prevDotX, prevDotY int
		first := true

		for i := 0; i+delay < n; i += step {
			x := samples[i]
			y := samples[i+delay]

			// Map [-1, 1] to dot coordinates.
			dotX := int((x + 1.0) * 0.5 * float64(dotCols-1))
			dotY := int((1.0 - y) * 0.5 * float64(dotRows-1))
			dotX = max(0, min(dotCols-1, dotX))
			dotY = max(0, min(dotRows-1, dotY))

			grid[dotY*dotCols+dotX] = true

			// Interpolate between consecutive points for smoother curves.
			if !first {
				dx := dotX - prevDotX
				dy := dotY - prevDotY
				adx := dx
				if adx < 0 {
					adx = -adx
				}
				ady := dy
				if ady < 0 {
					ady = -ady
				}
				steps := max(adx, ady)
				if steps > 0 && steps < 30 {
					for s := 1; s < steps; s++ {
						mx := prevDotX + dx*s/steps
						my := prevDotY + dy*s/steps
						if mx >= 0 && mx < dotCols && my >= 0 && my < dotRows {
							grid[my*dotCols+mx] = true
						}
					}
				}
			}

			prevDotX = dotX
			prevDotY = dotY
			first = false
		}
	}

	// Convert dot grid to Braille characters.
	lines := make([]string, height)
	for row := range height {
		var content strings.Builder
		for ch := range PanelWidth {
			var braille rune = '\u2800'
			for dr := range 4 {
				for dc := range 2 {
					if grid[(row*4+dr)*dotCols+ch*2+dc] {
						braille |= brailleBit[dr][dc]
					}
				}
			}
			content.WriteRune(braille)
		}
		lines[row] = specWrap(float64(height-1-row)/float64(height), content.String())
	}

	return strings.Join(lines, "\n")
}
