using Accord.Video;
using Accord.Video.DirectShow;
using Common.system;
using NAudio.Wave;
using System;
using System.Data;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;

namespace XHWK.WKTool
{
    using System.Linq;
    using system;

    /// <summary>
    /// DeviceWindow.xaml 的交互逻辑
    /// </summary>
    public partial class DeviceWindow
    {
        private bool _cameraGood;
        private bool _microphoneGood;
        private bool _loudspeakerGood;

        public DeviceWindow()
        {
            InitializeComponent();
            MicrophoneSetting.Click += MicrophoneSetting_Click;
            CameraCheck();
        }

        private void MicrophoneSetting_Click(object sender, RoutedEventArgs e)
        {
            Process.Start("mmsys.cpl");
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Initialize()
        {
            TxbCamera.Text = "";
            TxbSpeaker.Text = "";
            TxbMicrophone.Text = "";
        }

        /// <summary>
        /// 窗体移动
        /// </summary>
        /// <param name="sender">
        /// </param>
        /// <param name="e">
        /// </param>
        private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DragMove();
        }

        /// <summary>
        /// 关闭当前页
        /// </summary>
        /// <param name="sender">
        /// </param>
        /// <param name="e">
        /// </param>
        private void BtnDown_Click(object sender, RoutedEventArgs e)
        {
            imgPlayer.Visibility = Visibility.Hidden;
            CloseCamera();
            if (_waveIn != null)
            {
                _waveIn.StopRecording();
            }
            Close();
        }

        #region 摄像头

        private void CameraCheck()
        {
            HidePage();
            GridCamera.Visibility = Visibility.Visible;
            var devs = new FilterInfoCollection(FilterCategory.VideoInputDevice); //获取摄像头列表
            var allCamera = devs.Where
                    (x => x.Name != "screen-capture-recorder" && x.Name != "OBS Virtual Camera")
                .ToList();
            CmbCameraList.ItemsSource = allCamera;
            if (allCamera.Count > 0)
            {
                CmbCameraList.SelectedIndex = 0;
                App.CameraName = allCamera[0].MonikerString;
            }
        }

        private void CmbCameraList_SelectionChanged
            (object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            Console.WriteLine(@"选择变化");
            CheckCamera();
        }

        private VideoCaptureDevice _camera; //用来操作摄像头

        /// <summary>
        /// 检测
        /// </summary>
        private void CheckCamera()
        {
            try
            {
                CloseCamera();
                imgPlayer.Visibility = Visibility.Visible;
                if (CmbCameraList.SelectedIndex >= 0)
                {
                    var info = CmbCameraList.SelectedItem as FilterInfo;
                    App.CameraName = info.MonikerString;
                    _camera = new VideoCaptureDevice(info.MonikerString);
                    //配置录像参数(宽,高,帧率,比特率等参数)VideoCapabilities这个属性会返回摄像头支持哪些配置
                    _camera.VideoResolution = _camera.VideoCapabilities[0];
                    _camera.NewFrame +=
                        Camera_NewFrame; //设置回调,aforge会不断从这个回调推出图像数据,SnapshotFrame也是有待比较
                    _camera.Start(); //打开摄像头
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteErrLog("【摄像头检测】（DeviceWindow）摄像头不可用：" + ex.Message, ex);
            }
        }

        private void CloseCamera()
        {
            try
            {
                if (_camera != null)
                {
                    _camera.SignalToStop();
                }
            }
            catch (Exception)
            {
                // ignored
            }
        }

        /// <summary>
        /// 摄像头输出回调
        /// </summary>
        private void Camera_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            Dispatcher.Invoke
            (
                () =>
                {
                    MemoryStream ms = new MemoryStream();
                    eventArgs.Frame.Save(ms, ImageFormat.Bmp);
                    BitmapImage image = new BitmapImage();
                    image.BeginInit();
                    image.StreamSource = new MemoryStream(ms.GetBuffer());
                    ms.Close();
                    image.EndInit();
                    imgPlayer.Source = image;
                }
            ); //同步显示
        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="sender">
        /// </param>
        /// <param name="e">
        /// </param>
        private void BtnCameraStop_Click(object sender, RoutedEventArgs e)
        {
            if (_camera != null)
            {
                _camera.SignalToStop();
            }
        }

        #endregion 摄像头

        #region 扬声器

        /// <summary>
        /// 扬声器
        /// </summary>
        private void Speaker_Check()
        {
            CloseCamera();
            CmbCameraList.SelectedIndex = -1;
            HidePage();
            GridSpeaker.Visibility = Visibility.Visible;
        }

        /// <summary>
        /// 检测扬声器
        /// </summary>
        /// <param name="sender">
        /// </param>
        /// <param name="e">
        /// </param>
        private void BtnSpeakerDetection_Click(object sender, RoutedEventArgs e)
        {
            Console.WriteLine(@"播放");
            MediaAudio.Source = new Uri
                (FileToolsCommon.GetFileAbsolutePath("/Resources/audiotest.mp3"));
            MediaAudio.Position = TimeSpan.Zero;
            MediaAudio.Play();
            ImgAcousticWave.Visibility = Visibility.Visible;
        }

        #region 音频播放

        /// <summary>
        /// 音频播放 同步进度条和视频进度
        /// </summary>
        /// <param name="sender">
        /// </param>
        /// <param name="e">
        /// </param>
        private void MediaAudio_MediaOpened(object sender, RoutedEventArgs e)
        {
            Console.WriteLine(@"播放中。。。");
        }

        private void MediaAudio_MediaEnded(object sender, RoutedEventArgs e)
        {
            MediaAudio.Stop();
            MediaAudio.Position = TimeSpan.Zero;
        }

        #endregion 音频播放

        #endregion 扬声器

        #region 麦克风

        /// <summary>
        /// 麦克风
        /// </summary>
        /// <param name="e">
        /// </param>
        private async void Microphone_Check()
        {
            MediaAudio.Stop();
            ImgAcousticWave.Visibility = Visibility.Collapsed;
            HidePage();
            GridMicrophone.Visibility = Visibility.Visible;
            DataTable data = new DataTable();
            data.Columns.Add("Value");
            data.Columns.Add("Key");
            await Task.Run
            (
                () =>
                {
                    for (int n = 0; n < WaveIn.DeviceCount; n++)
                    {
                        var caps = WaveIn.GetCapabilities(n);

                        //创建一行
                        DataRow row = data.NewRow();
                        //将此行添加到table中
                        data.Rows.Add(row);
                        data.Rows[n]["Value"] = caps.ProductName;
                        data.Rows[n]["Key"] = n + "";
                    }
                }
            );
            CmbMicrophoneList.ItemsSource = data.DefaultView;
            if (WaveIn.DeviceCount > 0)
            {
                CmbMicrophoneList.SelectedIndex = 0;
            }
        }

        private WaveInEvent _waveIn;

        private void CmbMicrophoneList_SelectionChanged
            (object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (_waveIn != null)
            {
                _waveIn.StopRecording();
            }
            volumeProgressBar.Value = 0;
            if (CmbMicrophoneList.SelectedIndex >= 0)
            {
                var selectIndex = CmbMicrophoneList.SelectedIndex;
                ThreadPool.QueueUserWorkItem
                (
                    (item) =>
                    {
                        _waveIn = new WaveInEvent();
                        _waveIn.DeviceNumber = selectIndex;

                        //开始录音，写数据
                        _waveIn.DataAvailable += (o, e1) =>
                        {
                            byte[] buf = e1.Buffer;
                            float maxNumber = 0;
                            for (int index = 0; index < buf.Length; index += 2)
                            {
                                short sample = (short)((buf[index + 1] << 8) | buf[index + 0]);
                                float sample32 = sample / 32768f;
                                sample32 = Math.Abs(sample32);
                                if (sample32 > maxNumber)
                                {
                                    maxNumber = sample32;
                                }
                            }
                            Dispatcher.Invoke
                            (
                                () =>
                                {
                                    volumeProgressBar.Value = maxNumber * 100;
                                }
                            );
                        };

                        //结束录音
                        _waveIn.RecordingStopped += (s, a) =>
                        {
                            _waveIn.Dispose();
                        };
                        _waveIn.StartRecording();
                    }
                );
            }
        }

        #endregion 麦克风

        #region 页面切换

        /// <summary>
        /// 检测页
        /// </summary>
        private void result_show()
        {
            HidePage();
            GridDetection.Visibility = Visibility.Visible;
            if (_cameraGood)
            {
                TxbCamera.Text = "可用";
            }
            else
            {
                TxbCamera.Text = "不可用";
            }
            if (_loudspeakerGood)
            {
                TxbSpeaker.Text = "可用";
            }
            else
            {
                TxbSpeaker.Text = "不可用";
            }
            if (_microphoneGood)
            {
                TxbMicrophone.Text = "可用";
            }
            else
            {
                TxbMicrophone.Text = "不可用";
            }
        }

        /// <summary>
        /// 隐藏页
        /// </summary>
        private void HidePage()
        {
            GridDetection.Visibility = Visibility.Collapsed;
            GridCamera.Visibility = Visibility.Collapsed;
            GridSpeaker.Visibility = Visibility.Collapsed;
            GridMicrophone.Visibility = Visibility.Collapsed;
            try
            {
                CameraHelper.CloseDevice();
            }
            catch (Exception)
            {
                // ignored
            }
        }

        #endregion 页面切换

        #region 事件

        private void btn_camera_good_Click(object sender, RoutedEventArgs e)
        {
            _cameraGood = true;
            Speaker_Check();
        }

        private void btn_camera_bad_Click(object sender, RoutedEventArgs e)
        {
            _cameraGood = false;
            Speaker_Check();
        }

        private void btn_speaker_good_Click(object sender, RoutedEventArgs e)
        {
            _loudspeakerGood = true;
            Microphone_Check();
        }

        private void btn_speaker_bad_Click(object sender, RoutedEventArgs e)
        {
            _loudspeakerGood = false;
            Microphone_Check();
        }

        private void btn_microphone_good_Click(object sender, RoutedEventArgs e)
        {
            if (_waveIn != null)
            {
                _waveIn.StopRecording();
            }
            _microphoneGood = true;
            result_show();
            CmbMicrophoneList.SelectedIndex = -1;
        }

        private void btn_microphone_bad_Click(object sender, RoutedEventArgs e)
        {
            if (_waveIn != null)
            {
                _waveIn.StopRecording();
            }
            _microphoneGood = false;
            result_show();
            CmbMicrophoneList.SelectedIndex = -1;
        }

        /// <summary>
        /// 重新
        /// </summary>
        /// <param name="sender">
        /// </param>
        /// <param name="e">
        /// </param>
        private void BtnDetection_Click(object sender, RoutedEventArgs e)
        {
            CameraCheck();
        }

        #endregion 事件
    }
}
