using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using DayTimePickControl;
using Helper;
using NetSDKCS;

namespace PlayBackDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        #region field
        private IntPtr m_LoginHandle = IntPtr.Zero;
        private IntPtr m_PlayHandle = IntPtr.Zero;
        private IntPtr m_FileHandle = IntPtr.Zero;
        private NET_DEVICEINFO_Ex m_DeviceInfo;
        private PlaySpeed CurrentSpeed = PlaySpeed.NORMAL;
        private readonly fDisConnectCallBack m_DisConnectHandle;
        private readonly fDownLoadPosCallBack m_DownLoadPosHandle;
        private readonly fTimeDownLoadPosCallBack m_TimeDownLoadPosHandle;
        private PlayBackByTimePage playBackByTimePage = new PlayBackByTimePage();

        //play back config 
        public DateTime m_PlayBack_StartTime { get; set; }
        public DateTime m_PlayBack_EndTime { get; set; }
        public int m_PlayBack_Channel { get; set; }
        public int m_PlayBack_StreamType { get; set; }
        public EM_RECORD_TYPE m_PlayBack_recordType { get; set; }

        //play process param
        private DispatcherTimer m_DispatcherTimer = new DispatcherTimer();
        private NET_TIME m_OsdTime = new NET_TIME();
        private NET_TIME m_OsdStartTime = new NET_TIME();
        private NET_TIME m_OsdEndTime = new NET_TIME();

        //download config
        public DateTime m_Download_StartTime { get; set; }
        public DateTime m_Download_EndTime { get; set; }
        public int m_Download_Channel { get; set; }
        public int m_Download_StreamType { get; set; }
        public EM_RECORD_TYPE m_Download_recordType { get; set; }

        #endregion //field

        public MainWindow()
        {
            InitializeComponent();
            PlayBackFrame.Navigate(playBackByTimePage);

            m_DisConnectHandle = new fDisConnectCallBack(DisConnectCallBack);
            m_TimeDownLoadPosHandle = new fTimeDownLoadPosCallBack(TimeDownLoadPosCallBack);
            m_DownLoadPosHandle = new fDownLoadPosCallBack(DownLoadPosCallBack);
        }
        
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            LogHelper.WriteWithMethod("Enter");
            try
            {
                NETClient.Init(m_DisConnectHandle, IntPtr.Zero, null);//don't use "NETClient.Init(DisConnectCallBack, IntPtr.Zero, null)" whick the delegate will be garbage collected
            }
            catch (Exception ex)
            {
                this.Hide();
                MessageBox.Show(ex.Message);
                Application.Current.Shutdown();
            }
            DispatcherTimerInit();
            SetPlayBackControl(false);
            LogHelper.WriteWithMethod("Leave");
        }

        /// <summary>
        /// clean up SDK before app close
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            LogHelper.WriteWithMethod("Enter");
            try
            {
                NETClient.Cleanup();
            }
            catch (Exception)
            {
                //don't care
            }
            LogHelper.WriteWithMethod("Leave");
            
        }

        /// <summary>
        /// device login
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Login_Click(object sender, RoutedEventArgs e)
        {
            LogHelper.WriteWithMethod("Enter");
            ushort usPort;//store port
            try
            {
                if (string.IsNullOrWhiteSpace(ipInput.Text))
                {
                    MessageBox.Show((string)App.Current.TryFindResource("ID_LOGIN_IP_ERROR"));
                    return;
                }
                if (!ushort.TryParse(portInput.Text, out usPort))
                {
                    MessageBox.Show((string)App.Current.TryFindResource("ID_LOGIN_PORT_ERROR"));
                    return;
                }
                if (string.IsNullOrWhiteSpace(userInput.Text))
                {
                    MessageBox.Show((string)App.Current.TryFindResource("ID_LOGIN_USERNAME_ERROR"));
                    return;
                }
                m_LoginHandle = NETClient.Login(ipInput.Text, usPort, userInput.Text, passwordInput.Password, EM_LOGIN_SPAC_CAP_TYPE.TCP, IntPtr.Zero, ref m_DeviceInfo);
                if (IntPtr.Zero == m_LoginHandle)
                {
                    MessageBox.Show((string)App.Current.TryFindResource("ID_LOGIN_ERROR"));
                }
                else//success
                {
                    btnLogin.IsEnabled = false;
                    btnLogout.IsEnabled = true;
                    playBackByTimePage.SetChannelSource(m_DeviceInfo.nChanNum);
                    ControlPart.IsEnabled = true;
                }
            }
            catch (NETClientExcetion ex)
            {
                MessageBox.Show(ex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            LogHelper.WriteWithMethod("Leave");
        }

        /// <summary>
        /// only number can input
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void portInput_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            LogHelper.WriteWithMethod("Enter");
            try
            {
                Convert.ToUInt32(e.Text);
                e.Handled = false;
            }
            catch (Exception ex)
            {
                LogHelper.WriteException(ex);
                e.Handled = true;
            }
            LogHelper.WriteWithMethod("Leave");
        }

        //device logout
        private void Logout_Click(object sender, RoutedEventArgs e)
        {
            LogHelper.WriteWithMethod("Enter");
            try
            {
                StopDownLoad();
                StopPlayBack(true);

                bool result = NETClient.Logout(m_LoginHandle);
                if (result)
                {
                    m_LoginHandle = IntPtr.Zero;
                    btnLogin.IsEnabled = true;
                    btnLogout.IsEnabled = false;
                    playWindow.Refresh();
                    ControlPart.IsEnabled = false;
                }
            }
            catch (NETClientExcetion ex)
            {
                MessageBox.Show(ex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            LogHelper.WriteWithMethod("Leave");
        }

        #region main function(download, playback) method

        /// <summary>
        /// Set the record and stream type in video playback and download by time
        /// </summary>
        /// <param name="nStreamType">StreamType</param>
        /// <param name="emRecordType">RecordType</param>
        public void SetDeviceModel(int nStreamType, EM_RECORD_TYPE emRecordType)
        {
            LogHelper.WriteWithMethod("Enter");
            //start play
            IntPtr pStream = IntPtr.Zero;
            IntPtr pRecordType = IntPtr.Zero;
            try
            {
                //set streamType
                pStream = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)));
                Marshal.StructureToPtr(nStreamType, pStream, true);
                NETClient.SetDeviceMode(m_LoginHandle, EM_USEDEV_MODE.RECORD_STREAM_TYPE, pStream);

                //set recordType
                int nRecordType = (int)emRecordType;
                pRecordType = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)));
                Marshal.StructureToPtr(nRecordType, pRecordType, true);
                NETClient.SetDeviceMode(m_LoginHandle, EM_USEDEV_MODE.RECORD_TYPE, pRecordType);
            }
            catch (NETClientExcetion nex)
            {
                MessageBox.Show(nex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                Marshal.FreeHGlobal(pStream);
                Marshal.FreeHGlobal(pRecordType);
            }
            LogHelper.WriteWithMethod("Leave");
        }

        public void Download()
        {
            LogHelper.WriteWithMethod("Enter");
            System.Windows.Forms.SaveFileDialog sfd = new System.Windows.Forms.SaveFileDialog();
            sfd.Filter = "dav|*.dav";
            string path = string.Empty;
            if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                path = sfd.FileName;
            }
            else //user close the dialog
            {
                LogHelper.WriteWithMethod("Leave");
                return;
            }

            SetDeviceModel(m_Download_StreamType, m_Download_recordType);//Set stream type, and record type

            try
            {
                m_FileHandle = NETClient.DownloadByTime(m_LoginHandle, m_Download_Channel, EM_QUERY_RECORD_TYPE.ALL, m_Download_StartTime, m_Download_EndTime, path, m_TimeDownLoadPosHandle, IntPtr.Zero, null, IntPtr.Zero, IntPtr.Zero);
                if (IntPtr.Zero != m_FileHandle)
                {
                    playBackByTimePage.DL_Button.IsEnabled = false;
                    playBackByTimePage.DL_Stop.IsEnabled = true;
                }
            }
            catch (NETClientExcetion netEx)
            {
                MessageBox.Show(netEx.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            LogHelper.WriteWithMethod("Leave");
        }

        public void StopDownLoad()
        {
            LogHelper.WriteWithMethod("Enter");
            if (IntPtr.Zero != m_FileHandle)
            {
                bool ret = NETClient.StopDownload(m_FileHandle);
                if (ret)
                {
                    playBackByTimePage.DL_ProcessBar.Value = 0;
                    playBackByTimePage.DL_Button.IsEnabled = true;
                    playBackByTimePage.DL_Stop.IsEnabled = false;
                }
                m_FileHandle = IntPtr.Zero;
            }
            LogHelper.WriteWithMethod("Leave");
        }
        
        public void StartPlayBack()
        {
            LogHelper.WriteWithMethod("Enter");
            SetUIWait ();
            if (IntPtr.Zero==m_LoginHandle)
            {
                return;
            }

            //stop play
            if (IntPtr.Zero != m_PlayHandle)
            {
                StopPlayBack();
            }

            SetDeviceModel(m_PlayBack_StreamType, m_PlayBack_recordType);//Set stream type, and record type

            //start play
            IntPtr pStream = IntPtr.Zero;
            IntPtr pRecordType = IntPtr.Zero;
            try
            {
                //package playback param
                NET_IN_PLAY_BACK_BY_TIME_INFO stuInfo = new NET_IN_PLAY_BACK_BY_TIME_INFO();
                NET_OUT_PLAY_BACK_BY_TIME_INFO stuOut = new NET_OUT_PLAY_BACK_BY_TIME_INFO();
                stuInfo.stStartTime = NET_TIME.FromDateTime(m_PlayBack_StartTime);
                stuInfo.stStopTime = NET_TIME.FromDateTime(m_PlayBack_EndTime);
                stuInfo.hWnd = this.playWindow.Handle;
                stuInfo.cbDownLoadPos = m_DownLoadPosHandle;
                stuInfo.dwPosUser = IntPtr.Zero;
                stuInfo.fDownLoadDataCallBack = null;
                stuInfo.dwDataUser = IntPtr.Zero;
                stuInfo.nPlayDirection = 0;
                stuInfo.nWaittime = 5000;

                m_PlayHandle = NETClient.PlayBackByTime(m_LoginHandle, m_PlayBack_Channel, stuInfo, ref stuOut);
                
            }
            catch (NETClientExcetion nex)
            {
                MessageBox.Show(nex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                Marshal.FreeHGlobal(pStream);
                Marshal.FreeHGlobal(pRecordType);
            }
            if (IntPtr.Zero != m_PlayHandle)
            {
                SetPlayBackControl(true);
                m_DispatcherTimer.Start();
            }
            SetUIUnWait();
            LogHelper.WriteWithMethod("Leave");
        }
        
        public bool StopPlayBack(bool bClearTimeBlock = false)
        {
            LogHelper.WriteWithMethod("Enter");
            bool bResult = false;
            if (IntPtr.Zero != m_PlayHandle)
            {
                try
                {
                    if (m_DispatcherTimer.IsEnabled)
                    {
                        m_DispatcherTimer.Stop();
                    }
                    bResult = NETClient.PlayBackControl(m_PlayHandle, PlayBackType.Stop);
                    m_PlayHandle = IntPtr.Zero;
                }
                catch (NETClientExcetion nex)
                {
                    MessageBox.Show(nex.Message);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            if (bClearTimeBlock & bResult)
            {
                dayTimePicker.ClearTimeBlock();
                dayTimePicker.CurrentTimeOfSecond = 0;
                playWindow.Refresh();
            }
            ShowPlaySpeed(0);
            SetPlayBackControl(false);
            LogHelper.WriteWithMethod("Leave");
            return bResult;
        }
        #endregion

        #region callBack method
        private void DisConnectCallBack(IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser)
        {
            LogHelper.WriteWithMethod("Enter");
            MessageBox.Show(string.Format((string)App.Current.TryFindResource("ID_DISCONNECT"), Marshal.PtrToStringAnsi(pchDVRIP)));
            LogHelper.WriteWithMethod("Leave");
        }

        private void TimeDownLoadPosCallBack(IntPtr lPlayHandle, uint dwTotalSize, uint dwDownLoadSize, int index, NET_RECORDFILE_INFO recordfileinfo, IntPtr dwUser)
        {
            if (lPlayHandle!=m_FileHandle)
            {
                return;
            }
            int downLoadOver = -1;

            if ((uint)downLoadOver != dwDownLoadSize)
            {
                this.Dispatcher.BeginInvoke((Action)(() =>
                {
                    playBackByTimePage.DL_ProcessBar.Value = dwDownLoadSize;
                    playBackByTimePage.DL_ProcessBar.Maximum = dwTotalSize;
                }));
            }
            else
            {
                this.Dispatcher.BeginInvoke((Action)StopDownLoad);
            }
        }
        private void DownLoadPosCallBack(IntPtr lPlayHandle, uint dwTotalSize, uint dwDownLoadSize, IntPtr dwUser)
        {
           
        }


        #endregion//delegate

        private void dayTimePicker_OnTimeClick(object sender, _DDayTimePickSDKEvents_OnTimeClickEvent e)
        {
            LogHelper.WriteWithMethod("Enter");
            bool bIsTimeExist = dayTimePicker.IsTimeExist(e.nHour, e.nMinute, e.nSecond);
            
            if (bIsTimeExist)
            {
                m_DispatcherTimer.Stop();
                StopPlayBack();
                m_PlayBack_StartTime = m_PlayBack_StartTime.AddHours(e.nHour - m_PlayBack_StartTime.Hour);
                m_PlayBack_StartTime = m_PlayBack_StartTime.AddMinutes(e.nMinute - m_PlayBack_StartTime.Minute);
                m_PlayBack_StartTime = m_PlayBack_StartTime.AddSeconds(e.nSecond - m_PlayBack_StartTime.Second);

                StartPlayBack();
            }
            else
            {
               //could do sth or do noth.
            }
            LogHelper.WriteWithMethod("Leave");
        }

        public void QueryTimeBlock()
        {
            LogHelper.WriteWithMethod("Enter");
            SetUIWait();

            dayTimePicker.ClearTimeBlock();

            SetDeviceModel(m_PlayBack_StreamType, m_PlayBack_recordType);//Set stream type, and record type

            try
            {
                DateTime startTime = m_PlayBack_StartTime.Date;
                DateTime endTime = startTime.AddDays(1).AddSeconds(-1);
                NET_RECORDFILE_INFO[] array_RecordFile_Info = new NET_RECORDFILE_INFO[2000];
                EM_QUERY_RECORD_TYPE query_Record_Type;
                switch (m_PlayBack_recordType)
                {
                    case EM_RECORD_TYPE.ALL:
                        query_Record_Type = EM_QUERY_RECORD_TYPE.ALL;
                        break;
                    case EM_RECORD_TYPE.ALARM:
                        query_Record_Type = EM_QUERY_RECORD_TYPE.ALARM;
                        break;
                    case EM_RECORD_TYPE.MOTION:
                        query_Record_Type = EM_QUERY_RECORD_TYPE.MOTION_DETECT;
                        break;
                    default:
                        query_Record_Type = EM_QUERY_RECORD_TYPE.ALL;
                        break;
                }
                int fileCount = 0;
                NETClient.QueryRecordFile(m_LoginHandle, m_PlayBack_Channel, query_Record_Type, startTime, endTime, null, ref array_RecordFile_Info, ref fileCount, 5000, false);
                for (int i = 0; i < Math.Min(fileCount, array_RecordFile_Info.Length); i++)
                {
                    NET_TIME startNetTime = array_RecordFile_Info[i].starttime.ToDateTime() < startTime ? NET_TIME.FromDateTime(startTime) : array_RecordFile_Info[i].starttime;
                    NET_TIME endNetTime = array_RecordFile_Info[i].endtime.ToDateTime() > endTime ? NET_TIME.FromDateTime(endTime) : array_RecordFile_Info[i].endtime;
                    int nStartSecond = (int)(startNetTime.dwHour * 3600 + startNetTime.dwMinute * 60 + startNetTime.dwSecond);
                    int nEndSecond = (int)(endNetTime.dwHour * 3600 + endNetTime.dwMinute * 60 + endNetTime.dwSecond);
                    if (nEndSecond > nStartSecond)
                    {
                        dayTimePicker.AddTimeBlock(nStartSecond, nEndSecond, 0 | (255 << 8) | 0);//RGB
                    }
                }
            }
            catch (NETClientExcetion nex)
            {
                MessageBox.Show(nex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            SetUIUnWait();
            LogHelper.WriteWithMethod("Leave");
        }

        #region background worker,for refresh play back's process bar

        private void DispatcherTimerInit()
        {
            LogHelper.WriteWithMethod("Enter");
            m_DispatcherTimer.Interval = TimeSpan.FromMilliseconds(500);
            m_DispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
            LogHelper.WriteWithMethod("Leave");
        }

        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                bool b = NETClient.GetPlayBackOsdTime(m_PlayHandle, ref m_OsdTime, ref m_OsdStartTime, ref m_OsdEndTime);
                if (m_OsdTime.ToDateTime().Date == m_PlayBack_StartTime.Date)
                {
                    if (m_OsdTime.ToDateTime() >= m_PlayBack_EndTime)//Current Time > End Time
                    {
                        m_OsdTime = NET_TIME.FromDateTime(m_PlayBack_EndTime);
                        StopPlayBack();
                        return;
                    }
                    dayTimePicker.CurrentTimeOfSecond = (int)(m_OsdTime.dwHour * 3600 + m_OsdTime.dwMinute * 60 + m_OsdTime.dwSecond);
                }
            }
            catch { }
        }

        #endregion background worker

        

        #region Play Control


        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            LogHelper.WriteWithMethod("Enter");
            StopPlayBack(true);
            LogHelper.WriteWithMethod("Leave");
        }

        private void btnSlow_Click(object sender, RoutedEventArgs e)
        {
            LogHelper.WriteWithMethod("Enter");
            bool result = false;
            if (IntPtr.Zero == m_PlayHandle)
            {
                return;
            }
            try
            {
                result = NETClient.PlayBackControl(m_PlayHandle, PlayBackType.Slow);
            }
            catch (NETClientExcetion nex)
            {
                MessageBox.Show(nex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            if (result)
            {
                ShowPlaySpeed(-1);
            }
            LogHelper.WriteWithMethod("Leave");
        }

        /// <summary>
        /// show play speed on ui
        /// </summary>
        /// <param name="nMode">0 means set speed to normal, &gt; 0 means speed up, &lt; 0 mean speed down</param>
        private void ShowPlaySpeed(int nMode)
        {
            LogHelper.WriteWithMethod("Enter");
            if (nMode == 0)
            {
                CurrentSpeed = PlaySpeed.NORMAL;
            }
            else if (nMode > 0)	// Speed up
            {
                if (CurrentSpeed >= PlaySpeed.MIN && CurrentSpeed < PlaySpeed.MAX)
                {
                    CurrentSpeed = (PlaySpeed)((int)CurrentSpeed + 1);
                }
            }
            else if (nMode < 0)	// Speed down
            {
                if (CurrentSpeed > PlaySpeed.MIN && CurrentSpeed <= PlaySpeed.MAX)
                {
                    CurrentSpeed = (PlaySpeed)((int)CurrentSpeed - 1);
                }
            }

            //show current speed on UI
            switch (CurrentSpeed)
            {
                
                case PlaySpeed.DOWN_16:
                    tbSpeed.Text = "1/16";
                    break;
                case PlaySpeed.DOWN_8:
                    tbSpeed.Text = "1/8X";
                    break;
                case PlaySpeed.DOWN_4:
                    tbSpeed.Text = "1/4X";
                    break;
                case PlaySpeed.DOWN_2:
                    tbSpeed.Text = "1/2X";
                    break;
                case PlaySpeed.NORMAL:
                    tbSpeed.Text = "1X";
                    break;
                case PlaySpeed.UP_2:
                    tbSpeed.Text = "2X";
                    break;
                case PlaySpeed.UP_4:
                    tbSpeed.Text = "4X";
                    break;
                case PlaySpeed.UP_8:
                    tbSpeed.Text = "8X";
                    break;
                case PlaySpeed.UP_16:
                    tbSpeed.Text = "16X";
                    break;
                default:
                    tbSpeed.Text = "";
                    break;
            }

            if (PlaySpeed.MAX == CurrentSpeed)
            {
                btnFast.IsEnabled = false;
                btnSlow.IsEnabled = true;
            }
            else if (PlaySpeed.MIN == CurrentSpeed)
            {
                btnFast.IsEnabled = true;
                btnSlow.IsEnabled = false;
            }
            else
            {
                btnFast.IsEnabled = true;
                btnSlow.IsEnabled = true;
            }
            LogHelper.WriteWithMethod("Leave");
        }

        enum PlaySpeed
        {
            MIN,					// min speed             
            DOWN_16=MIN,            // speed 1/16X
            DOWN_8,
            DOWN_4,
            DOWN_2,
            NORMAL,				    // normal speed
            UP_2,
            UP_4,
            UP_8,
            UP_16,
            MAX = UP_16,	        // max speed
        }

        private void btnFast_Click(object sender, RoutedEventArgs e)
        {
            LogHelper.WriteWithMethod("Enter");
            bool result = false;
            if (IntPtr.Zero == m_PlayHandle)
            {
                return;
            }
            try
            {
                result = NETClient.PlayBackControl(m_PlayHandle, PlayBackType.Fast);
            }
            catch (NETClientExcetion nex)
            {
                MessageBox.Show(nex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            if (result)
            {
                ShowPlaySpeed(1);
            }
            LogHelper.WriteWithMethod("Leave");
        }

        private void btnPause_Click(object sender, RoutedEventArgs e)
        {
            LogHelper.WriteWithMethod("Enter");
            bool result = false;
            if (IntPtr.Zero == m_PlayHandle)
            {
                return;
            }
            try
            {
                result=NETClient.PlayBackControl(m_PlayHandle, PlayBackType.Pause);
            }
            catch (NETClientExcetion nex)
            {
                MessageBox.Show(nex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            if (result)
            {
                btnPause.Visibility = Visibility.Collapsed;
                btnPlay.Visibility = Visibility.Visible;
                m_DispatcherTimer.Stop();
            }
            LogHelper.WriteWithMethod("Leave");
        }

        private void btnNormal_Click(object sender, RoutedEventArgs e)
        {
            LogHelper.WriteWithMethod("Enter");
            bool result = false;
            if (IntPtr.Zero == m_PlayHandle)
            {
                return;
            }
            try
            {
                result = NETClient.PlayBackControl(m_PlayHandle, PlayBackType.Normal);
            }
            catch (NETClientExcetion nex)
            {
                MessageBox.Show(nex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            if (result)
            {
                ShowPlaySpeed(0);
                btnPlay.Visibility = Visibility.Collapsed;
                btnPause.Visibility = Visibility.Visible;
            }
            LogHelper.WriteWithMethod("Leave");
        }

        private void btnPlay_Click(object sender, RoutedEventArgs e)
        {
            LogHelper.WriteWithMethod("Enter");
            bool result = false;
            if (IntPtr.Zero == m_PlayHandle)
            {
                return;
            }
            try
            {
                result = NETClient.PlayBackControl(m_PlayHandle, PlayBackType.Play);
            }
            catch (NETClientExcetion nex)
            {
                MessageBox.Show(nex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            if (result)
            {
                btnPlay.Visibility = Visibility.Collapsed;
                btnPause.Visibility = Visibility.Visible;
                m_DispatcherTimer.Start();
            }
            LogHelper.WriteWithMethod("Leave");
        }

        private void SetPlayBackControl(bool enable)
        {
            LogHelper.WriteWithMethod("Enter");
            btnPause.IsEnabled = enable;
            btnPlay.IsEnabled = enable;
            btnStop.IsEnabled = enable;
            btnSlow.IsEnabled = enable;
            btnFast.IsEnabled = enable;
            btnNormal.IsEnabled = enable;
            if (enable)
            {
                btnPlay.Visibility = Visibility.Collapsed;
                btnPause.Visibility = Visibility.Visible;
            }
            LogHelper.WriteWithMethod("Leave");
        }
        #endregion //play control

        #region UI Busy Operator
        private void SetUIWait()
        {
            this.Cursor = Cursors.Wait;
        }
        private void SetUIUnWait()
        {
            this.Cursor = Cursors.Arrow;
        }
        #endregion

        
    }
}
