import subprocess

import numpy as np
from pojagi_dsp.channel.generator.sine import SineWave
import sys
import datetime
from itertools import islice

from matplotlib import pyplot as plt
from scipy.io import wavfile

from pojagi_dsp.channel import Constantly
from pojagi_dsp.channel.filter.envelope import Envelope


SRATE = 44100


def test_sawtooth(
    fundamental: float,
    npartials: int = 10,
    seconds: float = 1.0,
):
    sine = Constantly(0, srate=SRATE)

    for idx in range(1, npartials):
        freq = fundamental * idx
        amp = 1 / idx

        partial = SineWave(freq, synchronize=True)
        partial *= amp
        sine += partial

    sine |= lambda g: (x / 3 for x in g)
    sine |= Envelope(
        [
            (0, 0.0),
            (int(SRATE * seconds / 2), 1.0),
            (SRATE * seconds, 0.0),
        ]
    )

    values = []
    for y in sine.of_duration(datetime.timedelta(seconds=seconds)):
        values.append(y)

    return values


def test_pitchbend(
    from_pitch: float,
    to_pitch: float,
    seconds: float = 1.0,
):
    sine = SineWave(hz=from_pitch, srate=SRATE)

    sig = sine | Envelope(
        [
            (0, 0.0),
            (int(SRATE * seconds / 2), 1.0),
            (SRATE * seconds, 0.0),
        ]
    )

    lfo = (SineWave(1/seconds, srate=SRATE) * 30)
    lfo += (SineWave(seconds) * 20)
    lfo = lfo.stream()

    values = []
    for idx in range(int(seconds * SRATE)):
        values.append(next(sig))
        # if idx % 5000 == 0:
        sine.hz = from_pitch + next(lfo)
        # print(from_pitch + next(lfo))
        # import time
        # time.sleep(0.001)

    return values


def do_test(values: list[float]):
    plt.plot(range(len(values)), values)
    plt.show()

    audio = np.array(values, dtype=np.float32)
    wavfile.write("/tmp/output.wav", SRATE, audio)

    with subprocess.Popen(["mplayer", "/tmp/output.wav"]) as p:
        p.wait()


if __name__ == "__main__":
    # do_test(test_sawtooth(55.0))
    do_test(test_pitchbend(110.0, 110.0, seconds=10))
