package dsp

import "math"

// Oscillator produces a sine wave at a configured frequency and sample rate.
type Oscillator struct {
	Frequency  float64
	SampleRate float64
	phase      float64
}

// Tick advances the oscillator by one sample and returns the current sine value.
func (o *Oscillator) Tick() float64 {
	if o.SampleRate <= 0 || o.Frequency == 0 {
		return 0
	}
	value := math.Sin(2 * math.Pi * o.phase)
	step := o.Frequency / o.SampleRate
	o.phase += step
	if o.phase >= 1 || o.phase < 0 {
		o.phase -= math.Floor(o.phase)
	}
	return value
}

// Reset brings the phase back to zero.
func (o *Oscillator) Reset() {
	o.phase = 0
}

// Phase returns the current phase of the oscillator in [0, 1).
func (o *Oscillator) Phase() float64 {
	return o.phase
}

// PilotGenerator emits the 19 kHz pilot tone required by FM stereo.
// Output is unity-normalized (peak ±1.0). The caller controls the
// actual injection level via the combiner gain.
type PilotGenerator struct {
	Oscillator
}

// NewPilotGenerator constructs a pilot tone generator for the given sample rate.
func NewPilotGenerator(sampleRate float64) PilotGenerator {
	return PilotGenerator{
		Oscillator: Oscillator{Frequency: 19000, SampleRate: sampleRate},
	}
}

// Sample returns the next pilot sample (unity amplitude).
func (p *PilotGenerator) Sample() float64 {
	return p.Oscillator.Tick()
}
