using System;
using System.IO;
using System.Threading;

using NAudio.Wave;

namespace XHWK.WKTool.Utils
{
    public class ZAudioRecordHelper
    {
        public enum RecordType
        {
            Loudspeaker = 0, // 扬声器
            Microphone = 1 //麦克风
        }

        public enum RecordState
        {
            Stop = 0,
            Start = 1,
            Pause = 2
        }

        //录制的类型
        private RecordType _t;

        private RecordState _state;

        //录制麦克风的声音
        private WaveInEvent _waveIn; //new WaveInEvent();

        //录制扬声器的声音
        private WasapiLoopbackCapture _capture; //new WasapiLoopbackCapture();

        //生成音频文件的对象
        private WaveFileWriter _writer;

        private string _audioFile;

        public ZAudioRecordHelper(string filePath, RecordType type)
        {
            _t = type;
            _audioFile = filePath;
            _state = RecordState.Pause;
            try
            {
                if (_t == RecordType.Microphone)
                {
                    _waveIn = new WaveInEvent();
                    _writer = new WaveFileWriter(_audioFile, _waveIn.WaveFormat);
                    //开始录音，写数据
                    _waveIn.DataAvailable += (s, a) =>
                    {
                        if (_state == RecordState.Start)
                        {
                            _writer.Write(a.Buffer, 0, a.BytesRecorded);
                        }
                    };

                    //结束录音
                    _waveIn.RecordingStopped += (s, a) =>
                    {
                        _writer.Dispose();
                        _writer = null;
                        _waveIn.Dispose();
                    };
                    _waveIn.StartRecording();
                }
                else
                {
                    _capture = new WasapiLoopbackCapture();
                    _writer = new WaveFileWriter(_audioFile, _capture.WaveFormat);
                    _capture.DataAvailable += (s, a) =>
                    {
                        if (_state == RecordState.Start)
                        {
                            _writer.Write(a.Buffer, 0, a.BytesRecorded);
                        }
                    };
                    //结束录音
                    _capture.RecordingStopped += (s, a) =>
                    {
                        _writer.Dispose();
                        _writer = null;
                        _capture.Dispose();
                    };
                    _capture.StartRecording();
                }
            }
            catch (Exception)
            {
                // ignored
            }
        }

        /// <summary>
        /// 开始录制
        /// </summary>
        public void StartRecordAudio()
        {
            _state = RecordState.Start;
        }

        /// <summary>
        /// 结束录制
        /// </summary>
        public void StopRecordAudio()
        {
            _state = RecordState.Stop;
            if (_t == RecordType.Microphone)
            {
                _waveIn.StopRecording();
            }
            else
            {
                _capture.StopRecording();
            }
        }

        /// <summary>
        /// 暂停录制
        /// </summary>
        public void PauseRecordAudio()
        {
            _state = RecordState.Pause;
        }

        /// <summary>
        /// 恢复录制
        /// </summary>
        public void ResumeRecordAudio()
        {
            _state = RecordState.Start;
        }

        /// <summary>
        /// 设备是否可用
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsDeviceGood(RecordType type)
        {
            string tempPath = Path.GetTempPath();
            // Console.WriteLine("临时路径:" + tempPath);
            WaveInEvent mWaveIn;
            WaveFileWriter mWriter = null;
            WasapiLoopbackCapture mCapture;
            try
            {
                if (type == RecordType.Microphone)
                {
                    string mAudioFile = Path.Combine(tempPath, "_microphone.mp3");
                    mWaveIn = new WaveInEvent();
                    mWriter = new WaveFileWriter(mAudioFile, mWaveIn.WaveFormat);
                    //开始录音，写数据
                    mWaveIn.DataAvailable += (s, a) => { mWriter.Write(a.Buffer, 0, a.BytesRecorded); };

                    //结束录音
                    mWaveIn.RecordingStopped += (s, a) =>
                    {
                        if (mWriter != null)
                        {
                            mWriter.Dispose();
                        }
                        mWriter = null;
                        mWaveIn.Dispose();
                        if (File.Exists(mAudioFile))
                        {
                            File.Delete(mAudioFile);
                        }
                    };
                    mWaveIn.StartRecording();
                    ThreadPool.QueueUserWorkItem(
                        o =>
                        {
                            Thread.Sleep(200);
                            mWaveIn.StopRecording();
                        }
                    );
                }
                else
                {
                    string mAudioFile = Path.Combine(tempPath, "_loudspeaker.mp3");
                    mCapture = new WasapiLoopbackCapture();
                    mWriter = new WaveFileWriter(mAudioFile, mCapture.WaveFormat);
                    mCapture.DataAvailable += (s, a) =>
                    {
                        mWriter?.Write(a.Buffer, 0, a.BytesRecorded);
                    };
                    //结束录音
                    mCapture.RecordingStopped += (s, a) =>
                    {
                        mWriter?.Dispose();
                        mWriter = null;
                        mCapture.Dispose();
                        if (File.Exists(mAudioFile))
                        {
                            File.Delete(mAudioFile);
                        }
                    };
                    mCapture.StartRecording();
                    ThreadPool.QueueUserWorkItem(
                        o =>
                        {
                            Thread.Sleep(200);
                            mCapture.StopRecording();
                        }
                    );
                }
            }
            catch (Exception)
            {
                if (mWriter != null)
                {
                    mWriter.Dispose();
                    mWriter = null;
                }
                return false;
            }

            return true;
        }
    }
}
