import time
import os
from importlib import resources

import fluidsynth

from atonatui.constants import NOTE_TO_MIDI, GENERAL_MIDI_PROGRAMS, SOUNDFONTS
from atonatui.settings_mixin import Settings


class AudioMixin:
    def __init__(self):
        self.fs = fluidsynth.Synth()
        self.fs.start(driver="alsa" if os.name != "nt" else "dsound")

        self.sf_id = None
        self.update_sf(SOUNDFONTS[Settings.INSTRUMENT])
        self.clear_screen()

    def update_sf(self, path):
        if self.sf_id is not None and self.sf_id != -1:
            self.fs.sfunload(self.sf_id)

        try:
            audio_dir = resources.files("atonatui").joinpath("assets/audio")
            sf2_path = str(audio_dir.joinpath(path))
        except Exception:
            sf2_path = os.path.join(os.path.dirname(__file__), "assets/audio", path)

        self.sf_id = self.fs.sfload(sf2_path)
        self.fs.program_select(0, self.sf_id, 0, GENERAL_MIDI_PROGRAMS[Settings.INSTRUMENT])

    def play(self, note_name, duration, rest=False):
        if note_name not in NOTE_TO_MIDI:
            return

        midi_num = NOTE_TO_MIDI[note_name]
        channel = 0
        velocity = 100

        if not rest:
            self.fs.noteon(channel, midi_num, velocity)

        time.sleep(duration)

        if not rest:
            self.fs.noteoff(channel, midi_num)

    def close(self):
        self.fs.delete()
