package classifier

import (
	"math"
)

// ExtractTemporalFeatures computes simple time-domain features from IQ.
func ExtractTemporalFeatures(iq []complex64) (envVar float64, zeroCross float64, instFreqStd float64, crest float64) {
	if len(iq) == 0 {
		return 0, 0, 0, 0
	}
	env := make([]float64, len(iq))
	var mean, rms float64
	for i, v := range iq {
		a := math.Hypot(float64(real(v)), float64(imag(v)))
		env[i] = a
		mean += a
		rms += a * a
	}
	mean /= float64(len(iq))
	rms = math.Sqrt(rms / float64(len(iq)))
	// env variance
	var sumVar float64
	for _, v := range env {
		d := v - mean
		sumVar += d * d
	}
	envVar = sumVar / float64(len(iq))
	if rms > 0 {
		crest = maxFloat(env) / rms
	}
	// zero-crossing on real part
	zc := 0
	for i := 1; i < len(iq); i++ {
		p := real(iq[i-1])
		c := real(iq[i])
		if (p >= 0 && c < 0) || (p < 0 && c >= 0) {
			zc++
		}
	}
	zeroCross = float64(zc) / float64(len(iq))
	// instantaneous frequency std
	if len(iq) > 1 {
		var sum, sumSq float64
		for i := 1; i < len(iq); i++ {
			p := iq[i-1]
			c := iq[i]
			num := float64(real(p))*float64(imag(c)) - float64(imag(p))*float64(real(c))
			den := float64(real(p))*float64(real(c)) + float64(imag(p))*float64(imag(c))
			v := math.Atan2(num, den)
			sum += v
			sumSq += v * v
		}
		n := float64(len(iq) - 1)
		mean := sum / n
		instFreqStd = math.Sqrt(sumSq/n - mean*mean)
	}
	return
}

func maxFloat(vals []float64) float64 {
	m := vals[0]
	for _, v := range vals {
		if v > m {
			m = v
		}
	}
	return m
}
