using Voile.Audio;
using Silk.NET.OpenAL;

namespace Voile.OpenAL;

public class OpenALSystem : AudioSystem
{
    public OpenALSystem()
    {
        _al = AL.GetApi();
        _alc = ALContext.GetApi();

        Init();
    }

    public override void PlaySound(Sound sound, float volume)
    {
        var buffer = CreateAlBuffer(sound.Buffer, sound.SampleRate, sound.Channel);
        var source = CreateAlSource(buffer);
        _al.SourcePlay(source);
    }

    public override void Update(double deltaTime)
    {
        throw new NotImplementedException();
    }

    private unsafe void Init()
    {
        _device = _alc.OpenDevice("");
        _context = _alc.CreateContext(_device, null);
        _alc.MakeContextCurrent(_context);
    }

    private uint CreateAlBuffer(ReadOnlyMemory<short> data, int sampleRate, SoundChannel channels)
    {
        var buffer = _al.GenBuffer();
        var format = channels == SoundChannel.Mono ? BufferFormat.Mono16 : BufferFormat.Stereo16;

        unsafe
        {
            _al.BufferData(buffer, format, data.Pin().Pointer, data.Length, sampleRate);
        }

        return buffer;
    }

    private uint CreateAlSource(uint buffer)
    {
        var source = _al.GenSource();
        _al.SetSourceProperty(source, SourceInteger.Buffer, buffer);
        return source;
    }

    private unsafe Device* _device;
    private ALContext _alc;
    private unsafe Context* _context;
    private AL _al;
}
