import datetime
import math
from typing import Optional

from pojagi_dsp.channel import ASignal

_2_PI = 2 * math.pi


class SineWave(ASignal[float]):
    def __init__(
        self,
        hz: float,
        phase: float = 0.0,  # radians
        srate: Optional[float] = None
    ):
        super().__init__(srate)
        self.hz = hz
        self.phase = phase

    @property
    def wavelength(self): return self.srate/self.hz

    def samples(self):
        """An iterator over one period."""
        # zero-ish, but not always zero (to keep things smooth)
        self.phase %= _2_PI

        while self.phase < _2_PI:
            inc = (_2_PI * self.hz)/self.srate
            yield math.sin(self.phase)
            self.phase += inc


if __name__ == "__main__":
    from matplotlib import pyplot as plt

    concert_a = 440
    cd_quality_srate = 44100
    sine = SineWave(concert_a, srate=cd_quality_srate)

    values = []
    hz = sine.hz
    # for _ in range(10):
    #     values += list(sine)

    for y in sine.of_duration(datetime.timedelta(milliseconds=10)):
        values.append(y)

    plt.plot(range(len(values)), values)
    plt.show()
