package fftutil

import "math"

func Hann(n int) []float64 {
	w := make([]float64, n)
	if n <= 1 {
		if n == 1 {
			w[0] = 1
		}
		return w
	}
	for i := 0; i < n; i++ {
		w[i] = 0.5 * (1 - math.Cos(2*math.Pi*float64(i)/float64(n-1)))
	}
	return w
}

func Spectrum(iq []complex64, window []float64) []float64 {
	plan := NewCmplxPlan(len(iq))
	return SpectrumWithPlan(iq, window, plan)
}

func SpectrumWithPlan(iq []complex64, window []float64, plan *CmplxPlan) []float64 {
	n := len(iq)
	if n == 0 {
		return nil
	}
	in := make([]complex128, n)
	for i := 0; i < n; i++ {
		v := iq[i]
		w := 1.0
		if len(window) == n {
			w = window[i]
		}
		in[i] = complex(float64(real(v))*w, float64(imag(v))*w)
	}
	out := make([]complex128, n)
	if plan != nil && plan.N() == n {
		plan.FFT(out, in)
	} else {
		NewCmplxPlan(n).FFT(out, in)
	}

	power := make([]float64, n)
	eps := 1e-12
	invN := 1.0 / float64(n)
	for i := 0; i < n; i++ {
		idx := (i + n/2) % n
		mag := cmplxAbs(out[idx]) * invN
		p := 20 * math.Log10(mag+eps)
		power[i] = p
	}
	return power
}

func SpectrumFromFFT(out []complex64) []float64 {
	n := len(out)
	if n == 0 {
		return nil
	}
	power := make([]float64, n)
	eps := 1e-12
	invN := 1.0 / float64(n)
	for i := 0; i < n; i++ {
		idx := (i + n/2) % n
		v := out[idx]
		mag := math.Hypot(float64(real(v)), float64(imag(v))) * invN
		p := 20 * math.Log10(mag+eps)
		power[i] = p
	}
	return power
}

func cmplxAbs(v complex128) float64 {
	return math.Hypot(real(v), imag(v))
}
