using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MotorSkill
{
    class MicrophoneDataFrame
    {
        // member data
        public byte[] data { get; set; }
        public int offset { get; set; }
        public int count { get; set; }

        public MicrophoneDataFrame(byte[] data, int offset, int count)
        {
            this.data = data;
            this.offset = offset;
            this.count = count;
        }
    }

    class MicrophoneDataStream
    {
        // audio data stream initialisation parameters 
        int sampleRate;
        int channels;
        public WaveIn waveSource;

        // callback called when new data is available
        private Action<MicrophoneDataFrame> callback;

        public static void testAvailability()
        {
            try
            {
                WaveIn tmp = new WaveIn(); ;
                tmp.WaveFormat = new WaveFormat();
                tmp.StartRecording();
                tmp.StopRecording();
            }
            catch(Exception e)
            {
                throw new MicrophoneFailedToOpenException();
            }
        }

        public MicrophoneDataStream(Action<MicrophoneDataFrame> callback, int sampleRate, int channels)
        {
            this.callback = callback;
            this.sampleRate = sampleRate;
            this.channels = channels;

            waveSource = new WaveIn();
            waveSource.WaveFormat = new WaveFormat(sampleRate, channels);

            waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
            waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);
        }

        public void Open()
        {
            try
            {
                waveSource.StartRecording();
            }
            catch (Exception e)
            {
                throw new MicrophoneFailedToOpenException();
            }
        }

        public void Close()
        {
            waveSource.StopRecording();
        }

        void waveSource_DataAvailable(object sender, WaveInEventArgs e)
        {
            callback(new MicrophoneDataFrame(e.Buffer, 0, e.BytesRecorded));
        }

        void waveSource_RecordingStopped(object sender, StoppedEventArgs e)
        {
            if (waveSource != null)
            {
                waveSource.Dispose();
                waveSource = null;
            }
        }
    }
    public class MicrophoneFailedToOpenException : Exception
    {
    }
    public class MicrophoneFailedToCloseException : Exception
    {
    }
}
