#region LICENSE
//
// Copyright (c) Microncode.com
// 
// This source is subject to the Microsoft Public License. 
// See https://opensource.org/licenses/ms-pl.html.
// All other rights reserved. 
// 
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 
//
#endregion

namespace CSWebCamExampleWPF
{
    using System;
    using System.Diagnostics;
    using System.Windows;
    using CSWebCam;
    using Microsoft.Win32;

    /// <summary>
    /// The main example of using the CSWebCam with WPF
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// Create new instance of the component
        /// </summary>
        Camera _Camera = new Camera();

        /// <summary>
        /// Constructor.
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            //Events
            _Camera.OperationOutput += new CSWebCam.Camera.OperationOutputEventHandler(OperationOutput);
            _Camera.OperationDone += new CSWebCam.Camera.OperationDoneEventHandler(OperationDone);
            _Camera.OperationStart += new CSWebCam.Camera.OperationStartEventHandler(OperationStart);
            _Camera.OperationError += new CSWebCam.Camera.OperationErrorEventHandler(OperationError);
            _Camera.OperationClosed += new CSWebCam.Camera.OperationClosedEventHandler(OperationClosed);


        }

        /// <summary>
        /// Close all instances of the FFmpeg.
        /// </summary>
        public void CloseAll()
        {
            if (_Camera.IsRun)
            {
                _Camera.Close();

                while (_Camera.IsRun)
                    try
                    {
                        System.Threading.Thread.Sleep(50);
                    }
                    catch (Exception) { }
            }
        }

        /// <summary>
        /// Open local camera.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmdOpenCam_Click(object sender, RoutedEventArgs e)
        {
            this.CloseAll();

            _Camera.VideoResolutionX = txtVideoResolutionX.Text;
            _Camera.VideoResolutionY = txtVideoResolutionY.Text;

            _Camera.VideoFPS = "30";
            _Camera.BufferSize = "100MB";

            _Camera.DispWinPixFmt = "yuv420p";

            //Set the preview
            _Camera.SetPicView(CameraPreviewWPF.Preview);

            //Open the device
            _Camera.OpenDevice(cboCamDevices.Text, cboAudioDevices.Text);

        }

        /// <summary>
        /// Window_Loaded.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //Create a new instance of the library with the direction of the ffmpeg libraries

            try
            {
                //Set the path of the ffmpeg libraries
                string LibsPath = "";

                //If the LibsPath is empty or "" the library will search for
                //the ffmpeg libraries under the path:
                //[AssemblyDirectory]\CSPlugins\FFmpeg\[x86|x64]\

                await _Camera.Init("UserName", "RegKey", LibsPath);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }


            //Get all the video / camera devices
            foreach (var videoDevice in _Camera.CameraDevices)
                cboCamDevices.Items.Add(videoDevice.Name);

            //Select the first
            cboCamDevices.SelectedIndex = 0;

            //Get all the audio devices
            foreach (var audioDevice in _Camera.AudioDevices)
                cboAudioDevices.Items.Add(audioDevice.Name);

            //Select the first
            cboAudioDevices.SelectedIndex = 0;

            //Select MP4 format
            cboDestinationFormat.Text = "MP4";
        }

        /// <summary>
        /// Close the camera.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmdCloseCam_Click(object sender, RoutedEventArgs e)
        {
            _Camera.Close();
        }

        /// <summary>
        /// Capture the camera to a video / audio file.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cboCapture_Click(object sender, RoutedEventArgs e)
        {
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.Filter = "AVI|*.avi|FLV|*.flv|MKV|*.mkv|MOV|*.mov|MP4|*.mp4|MTS|*.mts|MPEG|*.mpeg|WEBM|*.webm|WMV|*.wmv";
            saveFileDialog1.Title = "Save As File";
            saveFileDialog1.FilterIndex = cboDestinationFormat.SelectedIndex + 1;
            saveFileDialog1.ShowDialog();

            // If the file name is not an empty string open it for saving.
            if (saveFileDialog1.FileName != "")
            {
                this.CloseAll();

                //MessageBox.Show(saveFileDialog1.FileName);

                _Camera.VideoResolutionX = txtVideoResolutionX.Text;
                _Camera.VideoResolutionY = txtVideoResolutionY.Text;

                _Camera.VideoFPS = "30";
                _Camera.BufferSize = "100MB";

                _Camera.DispWinPixFmt = "yuv420p";

                //Set the preview
                _Camera.SetPicView(CameraPreviewWPF.Preview);

                //Open the device and save the results to a media file
                _Camera.OpenDevice(cboCamDevices.Text, cboAudioDevices.Text, saveFileDialog1.FileName);
            }
        }

        /// <summary>
        /// Stop capture.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cboStopCapture_Click(object sender, RoutedEventArgs e)
        {
            _Camera.Close();
        }

        /// <summary>
        /// Get the details of the selected camera device.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void cboCamDeviceDetails_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(await _Camera.GetDeviceOptionsVideo(cboCamDevices.Text));
        }

        /// <summary>
        /// Get the details of the selected audio device.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void cboAudioDeviceDetails_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(await _Camera.GetDeviceOptionsAudio(cboAudioDevices.Text));
        }

        #region Events

        /// <summary>
        /// Operation out put.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="output"></param>
        /// <param name="props"></param>
        public void OperationOutput(object sender, string output, OutputProperties props)
        {
            //Display the output
            Debug.WriteLine(output);

            //Get the frame
            Debug.Print("Frame: " + props.Frame.ToString());

            //Get the FPS
            Debug.Print("FPS: " + props.Fps.ToString());

            //Get the speed
            Debug.Print("Speed: " + props.Speed.ToString());

            //Get the time
            Debug.Print("Time: " + props.Time.ToString());
        }

        /// <summary>
        /// Operation done.
        /// </summary>
        /// <param name="sender"></param>
        public void OperationDone(object sender)
        {
            //Operation done
        }

        /// <summary>
        /// Operation started.
        /// </summary>
        /// <param name="sender"></param>
        public void OperationStart(object sender)
        {
            //Operation started
        }

        /// <summary>
        /// On Error.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="output"></param>
        public void OperationError(object sender, string output)
        {
            //Error:
            MessageBox.Show(output);
        }

        /// <summary>
        /// Operation closed.
        /// </summary>
        /// <param name="sender"></param>
        public void OperationClosed(object sender)
        {
            //Operation closed
        }

        #endregion

        /// <summary>
        /// Order a license.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmdOrderLicense_Click(object sender, RoutedEventArgs e)
        {
            /// In order to get your own UserName and RegKey and to distribute this library
            /// with your own projects for commercial or any other purpose, please order a license at:
            /// https://www.microncode.com/developers/cs-video-player/?cmd=order

            System.Diagnostics.Process.Start("https://www.microncode.com/developers/cs-video-player/?cmd=order");
        }
    }
}
