package utils

// RGBPixel represents an RGB color value
type RGBPixel struct {
	R, G, B uint8
}

// L4Colormap is the Black-Red-Yellow heat colormap from PerceptualColourMaps.jl
// Control points:
//
//	Index 0:   Black      (0.0, 0.0, 0.0)
//	Index 85:  Dark Red   (0.85, 0.0, 0.0)
//	Index 170: Orange-Red (1.0, 0.15, 0.0)
//	Index 255: Yellow     (1.0, 1.0, 0.0)
var L4Colormap [256]RGBPixel

func init() {
	// Generate L4 colormap using piecewise linear interpolation
	// This avoids overshoot issues with cubic splines
	controlPoints := []struct {
		idx int
		r   float64
		g   float64
		b   float64
	}{
		{0, 0.0, 0.0, 0.0},
		{85, 0.85, 0.0, 0.0},
		{170, 1.0, 0.15, 0.0},
		{255, 1.0, 1.0, 0.0},
	}

	for i := range 256 {
		// Find the segment we're in
		var seg int
		for seg = 0; seg < len(controlPoints)-1; seg++ {
			if i <= controlPoints[seg+1].idx {
				break
			}
		}
		if seg >= len(controlPoints)-1 {
			seg = len(controlPoints) - 2
		}

		// Linear interpolation within segment
		p0 := controlPoints[seg]
		p1 := controlPoints[seg+1]

		t := 0.0
		if p1.idx != p0.idx {
			t = float64(i-p0.idx) / float64(p1.idx-p0.idx)
		}

		L4Colormap[i] = RGBPixel{
			R: uint8((p0.r + t*(p1.r-p0.r)) * 255.0),
			G: uint8((p0.g + t*(p1.g-p0.g)) * 255.0),
			B: uint8((p0.b + t*(p1.b-p0.b)) * 255.0),
		}
	}
}

// ApplyL4Colormap converts a grayscale image to RGB using the L4 colormap
func ApplyL4Colormap(grayscale [][]uint8) [][]RGBPixel {
	if len(grayscale) == 0 || len(grayscale[0]) == 0 {
		return nil
	}

	rows := len(grayscale)
	cols := len(grayscale[0])

	result := make([][]RGBPixel, rows)
	for i := range result {
		result[i] = make([]RGBPixel, cols)
	}

	for y := range rows {
		for x := range cols {
			result[y][x] = L4Colormap[grayscale[y][x]]
		}
	}

	return result
}