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 = RecordType.microphone;

        private RecordState _state = RecordState.stop;

        //录制麦克风的声音
        private WaveInEvent waveIn = null; //new WaveInEvent();

        //录制扬声器的声音
        private WasapiLoopbackCapture capture = null; //new WasapiLoopbackCapture();

        //生成音频文件的对象
        private WaveFileWriter writer = null;

        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)
            {
            }
        }

        /// <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 = null;
            WaveFileWriter mWriter = null;
            WasapiLoopbackCapture mCapture = null;
            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) =>
                    {
                        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;
        }
    }
}