using System;
//#define SBS_VR
//#define SmartConnectSystems_VR
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using Microsoft.Win32;
using System.Xml;
using System.ServiceProcess;
//using System.Security.Permissions;
//using System.Security.Principal;
using VR2;

namespace VR2WinApp
{
    public partial class VR2AppMainForm : Form
    {
        public const string VR2_REG_KEY_ROOT = "SOFTWARE\\PC Best Networks Inc\\VoIP Recorder V2\\";
        public const string VR2_Service_Name = "PCBest Networks VoIP Recorder v2";

        VR2Main vr2;

        public bool _bExit;
        //public bool Started;
        //public bool Inited;

#if SBS_VR
        public const string VR2_TITLE = "Single Bill Solution VoIP Recorder v1.12";
#elif SmartConnectSystems_VR
        public const string VR2_TITLE = "SmartConnect Systems - SIP Voice Recorder";
#else
        public const string VR2_TITLE = "PCBest Networks VoIP Recorder V2.30b";
#endif
        public XmlDocument xmlCfg;

        public List<string> NICs;

        public static VR2AppMainForm main_form;

        public Queue<VR2Channel> event_queue;

        public int StartRecordingOnBoot;
        public string PasswordProtected = "";

        public int RunModel; // 0 = deskTop, 1 = win service, 2 = ManageClient Model

        public int ChanNum;

        public VR2WinAppClient vr_client;
        public bool serverConnected;
        public bool waiting_general;
        public string serverIP;
        public ushort serverPort;
        public bool serviceRunning;
        public int timerCount;

        public RTListenSoftphone rtPhone;

        public VR2AppMainForm()
        {
            InitializeComponent();

            _bExit = false;

            //Started = false;
            //Inited = false;

            NICs = new List<string>();

            main_form = this;

            StartRecordingOnBoot = 0;
            RunModel = 0;

            event_queue = new Queue<VR2Channel>();

            vr_client = new VR2WinAppClient();
            vr_client.main_form = this;

            serverIP = "127.0.0.1";
            serverPort = 1376;

            serviceRunning = false;

            timerCount = 0;

            ChanNum = 0;

            rtPhone = null;
        }

        private void VR2AppMainForm_Load(object sender, EventArgs e)
        {
            RegistryKey regkey;

            main_form = this;

#if SBS_VR
            sbsPictureBox.Visible = true;
            pcbestLogo.Visible = false;
            richTextBox1.Visible = false;
            runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
            sbsPictureBox.Visible = false;
            pcbestLogo.Visible = false;
            richTextBox1.Visible = false;
            runningModelToolStripMenuItem.Enabled = false;
            aboutToolStripMenuItem1.Enabled = false;
            aboutToolStripMenuItem.Enabled = false;
            popOutToolStripMenuItem.Enabled = false;
#else
            sbsPictureBox.Visible = false;
            pcbestLogo.Visible = true;
            richTextBox1.Visible = true;
            runningModelToolStripMenuItem.Enabled = true;
#endif

            this.Text = VR2_TITLE;

            notifyIcon1.ContextMenuStrip = contextMenuStrip1;
            notifyIcon1.Text = VR2_TITLE;

            /*
            string sSysPath = Environment.SystemDirectory;

            if (!File.Exists(sSysPath + "\\packet.dll") || !File.Exists(sSysPath + "\\wpcap.dll"))
            {
                string message = "Npcap or WinPcap is not installed! Please download it from https://nmap.org/npcap/ or https://www.winpcap.org/, and install it first.";
                string caption = "Error Detected - Missing Npcap/WinPcap Driver";
                MessageBoxButtons buttons = MessageBoxButtons.OK;
                DialogResult result;

                // Displays the MessageBox.
                result = MessageBox.Show(message, caption, buttons);

                _bExit = true;
                Close();

                return;
            }


            regkey = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\WinPcapInst");
            if (regkey == null)
            {
                string message = "Npcap or WinPcap is not installed! Please download it from https://nmap.org/npcap/ or https://www.winpcap.org/, and install it first.";
                string caption = "Error Detected - Missing Npcap/WinPcap Driver";

                MessageBoxButtons buttons = MessageBoxButtons.OK;
                DialogResult result;

                // Displays the MessageBox.
                result = MessageBox.Show(message, caption, buttons);

                _bExit = true;
                Close();

                return;
            }
            else
            {
                regkey.Close();
            }*/

            //2020-12-28 using new API instead to detect
            int pcap_type = VRAPIASM.VRAPIEnv.GetPcapDriverType();

            if (pcap_type == 0)
            {
                /*
                string message = "Npcap or WinPcap is not installed! Please download it from https://nmap.org/npcap/ or https://www.winpcap.org/, and install it first.";
                string caption = "Error Detected - Missing Npcap/WinPcap Driver";
                MessageBoxButtons buttons = MessageBoxButtons.OK;
                DialogResult result;

                // Displays the MessageBox.
                result = MessageBox.Show(message, caption, buttons);*/

                MissingPcap dlg = new MissingPcap();
                dlg.ShowDialog();


                _bExit = true;
                Close();

                return;
            }
            else if (pcap_type == 1)
            {
                //Winpcap
                LogoutText("WinPcap driver detected! " + VRAPIASM.VRAPIEnv.GetPcapDriverTypeStr());
            }
            else if (pcap_type == 2)
            {
                //Npcap
                LogoutText("Npcap driver detected! " + VRAPIASM.VRAPIEnv.GetPcapDriverTypeStr());
            }

            //string tmp;
            regkey = Registry.CurrentUser.CreateSubKey(VR2_REG_KEY_ROOT);
            if (regkey == null)
                return;

            Object obj = regkey.GetValue("RecordOnBoot");
            if (obj != null)
                StartRecordingOnBoot = (int)obj;

            obj = regkey.GetValue("PasswordProtected");
            if (obj != null)
                PasswordProtected = (string)obj;

            if (PasswordProtected.Length > 0)
            {
                ReqPassword dlg = new ReqPassword();
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    if (PasswordProtected != dlg.passwd)
                    {
                        regkey.Close();

                        MessageBox.Show("Wrong Password!");

                        _bExit = true;
                        Close();

                        return;
                    }
                }
                else
                {
                    regkey.Close();
                    _bExit = true;
                    Close();

                    return;
                }
            }

            obj = regkey.GetValue("RunModel");
            if (obj != null)
            {
                RunModel = (int)obj;
                obj = regkey.GetValue("ServerIP");
                if (obj != null)
                {
                    serverIP = (string)obj;
                }

                obj = regkey.GetValue("ServerPort");
                if (obj != null)
                {
                    int port = (int)obj;
                    serverPort = Convert.ToUInt16(port);
                }

            }
            else
            {
#if SBS_VR
#elif SmartConnectSystems_VR
#else
                //object is null, it is the first running, need to ask
                RunningModel dlg = new RunningModel();
                dlg.RunModel = RunModel;
                dlg.ServerIP = serverIP;
                dlg.ServerPort = serverPort;
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    RunModel = dlg.RunModel;
                    serverIP = dlg.ServerIP;
                    serverPort = dlg.ServerPort;
                    if (serverIP.Length == 0)
                        serverIP = "127.0.0.1";

                    regkey.SetValue("RunModel", RunModel);
                    regkey.SetValue("ServerIP", serverIP);
                    int port = serverPort;
                    regkey.SetValue("ServerPort", port);
                }
#endif
            }

            regkey.Close();

            if (LoadConfigFromXML() < 0)
            {
                _bExit = true;
                Close();
                return;
            }

            VRAPIASM.VRAPIEnv.InitCapture(0);

            short nicCount = VRAPIASM.VRAPIEnv.GetNICCount();

            if (nicCount <= 0)
            {
                VRAPIASM.VRAPIEnv.FreeCapture();
                MessageBox.Show("No Network Interface!");
                _bExit = true;
                Close();
                return;
            }
            else
            {
                for (short i = 0; i < nicCount; i++)
                {
                    string s = i.ToString() + " : " + VRAPIASM.VRAPIEnv.GetNICName(i) + " - " + VRAPIASM.VRAPIEnv.GetNICDescription(i);
                    short ipCount = VRAPIASM.VRAPIEnv.GetNICIPCount(i);
                    if (ipCount > 0)
                        s += " IP:";
                    for (short j = 0; j < ipCount; j++)
                    {
                        if (VRAPIASM.VRAPIEnv.GetNICIP(i, j) != "0.0.0.0")
                        {
                            s += VRAPIASM.VRAPIEnv.GetNICIP(i, j) + ";";
                        }
                    }

                    NICs.Add(s);
                }
                VRAPIASM.VRAPIEnv.FreeCapture();
            }

            startRecordingToolStripMenuItem.Enabled = true;
            stopRecordingToolStripMenuItem.Enabled = false;

            toolStripButtonPlay.Enabled = true;
            toolStripButtonStop.Enabled = false;

            recordingToolStripMenuItem.Text = "Status: Recording Stopped";
            toolStripStatusLabel1.Text = "Status: Recording Stopped";

            dataGridView1.Enabled = false;

            tbTotalChannels.Enabled = false;
            tbTotalChannels.Text = "";

            tbAvailableChannels.Enabled = false;
            tbAvailableChannels.Text = "";

            tbOfflineChannels.Enabled = false;
            tbOfflineChannels.Text = "";

            tbChannelInUse.Enabled = false;
            tbChannelInUse.Text = "";

            openRealtimeListenerToolStripMenuItem.Enabled = false;


            //start_here:
            if (RunModel == 0)
            {
                if (StartRecordingOnBoot == 1)
                {
                    Start();
                }
            }
            else if (RunModel == 1)
            {
#if SBS_VR
#elif SmartConnectSystems_VR
#else
                //service model
                try
                {
                    ServiceControllerStatus srvStatus = GetWinServiceStatus(VR2_Service_Name);
                    if (srvStatus == System.ServiceProcess.ServiceControllerStatus.Stopped)
                    {
                        serviceRunning = false;
                        timer1.Enabled = false;
                        timer2.Enabled = false;

                        startRecordingToolStripMenuItem.Enabled = true;
                        stopRecordingToolStripMenuItem.Enabled = false;

                        toolStripButtonPlay.Enabled = true;
                        toolStripButtonStop.Enabled = false;


                        //Started = false;
                        optionsToolStripMenuItem1.Enabled = true;
                        toolStripButtonOptions.Enabled = true;

                        dataGridView1.Enabled = false;

                        tbTotalChannels.Enabled = false;
                        tbTotalChannels.Text = "";

                        tbAvailableChannels.Enabled = false;
                        tbAvailableChannels.Text = "";

                        tbOfflineChannels.Enabled = false;
                        tbOfflineChannels.Text = "";

                        tbChannelInUse.Enabled = false;
                        tbChannelInUse.Text = "";

                        recordingToolStripMenuItem.Text = "Status: Recording Service Stopped";
                        toolStripStatusLabel1.Text = "Status: Recording Service Stopped";

#if SBS_VR
                        runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
                        runningModelToolStripMenuItem.Enabled = false;
#else
                        runningModelToolStripMenuItem.Enabled = true;
#endif
                    }
                    else if (srvStatus == System.ServiceProcess.ServiceControllerStatus.Running)
                    {
                        serviceRunning = true;
                        startRecordingToolStripMenuItem.Enabled = false;
                        stopRecordingToolStripMenuItem.Enabled = true;

                        toolStripButtonPlay.Enabled = false;
                        toolStripButtonStop.Enabled = true;

                        //Started = true;
                        optionsToolStripMenuItem1.Enabled = false;
                        toolStripButtonOptions.Enabled = false;

                        tbTotalChannels.Enabled = true;
                        tbAvailableChannels.Enabled = true;
                        tbOfflineChannels.Enabled = true;
                        tbChannelInUse.Enabled = true;

                        //tbTotalChannels.Text = vr2.ChannelCount.ToString();
                        //tbAvailableChannels.Text = vr2.ChannelCount.ToString();
                        tbOfflineChannels.Text = "0";
                        tbChannelInUse.Text = "";

                        timer1.Enabled = true;
                        timer2.Enabled = true;

                        recordingToolStripMenuItem.Text = "Status: Recording Service Running";
                        toolStripStatusLabel1.Text = "Status: Recording Service Running";

#if SBS_VR
                        runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
                        runningModelToolStripMenuItem.Enabled = false;
#else
                        runningModelToolStripMenuItem.Enabled = false;
#endif
                    }
                    else
                    {

                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());

                    //no service is installed
                    timer1.Enabled = false;

                    startRecordingToolStripMenuItem.Enabled = false;
                    stopRecordingToolStripMenuItem.Enabled = false;

                    toolStripButtonPlay.Enabled = false;
                    toolStripButtonStop.Enabled = false;


                    //Started = false;
                    optionsToolStripMenuItem1.Enabled = true;
                    toolStripButtonOptions.Enabled = true;

                    dataGridView1.Enabled = false;

                    tbTotalChannels.Enabled = false;
                    tbTotalChannels.Text = "";

                    tbAvailableChannels.Enabled = false;
                    tbAvailableChannels.Text = "";

                    tbOfflineChannels.Enabled = false;
                    tbOfflineChannels.Text = "";

                    tbChannelInUse.Enabled = false;
                    tbChannelInUse.Text = "";

                    recordingToolStripMenuItem.Text = "Status: N/A";
                    toolStripStatusLabel1.Text = "Status: N/A";

                    serviceRunning = false;

#if SBS_VR
                    runningModelToolStripMenuItem.Enabled = false;
#else
                    runningModelToolStripMenuItem.Enabled = true;
#endif
                }

                //start_here1:
                if (serviceRunning)
                {
                    IntPtr resConnect = vr_client.ConnectTo(serverIP, serverPort);

                    if (resConnect == IntPtr.Zero)
                    {
                        LogoutText("Cannot connect to recorder service!");
                        vr_client.Disconnect();
                        timer2.Enabled = false;
                    }
                }
                else
                {
                }

#endif
            }
            else if (RunModel == 2) //ManageClient
            {
                /*
                uint resConnect = vr_client.ConnectTo(serverIP, serverPort);

                if (resConnect == 0)
                {
                    //LogoutText("Cannot connect to recorder service!");
                    vr_client.Disconnect();
                    timer2.Enabled = false;

                    recordingToolStripMenuItem.Text = "Status: Cannot connect to server.";
                    toolStripStatusLabel1.Text = "Status: Cannot connect to server.";

                }
                else
                {
                    recordingToolStripMenuItem.Text = "Status: Connected to server.";
                    toolStripStatusLabel1.Text = "Status: Connected to server.";
                }*/

                StartManageClient();
            }
        }

        public bool StartPreCheck(string cfgFile)
        {
            if (!ReloadXMLCfg())
                return false;

            XmlElement root = xmlCfg.DocumentElement;
            XmlNode tmpNode = root.SelectSingleNode("//VoiceRecorder/AudioRootFolder");
            if (tmpNode != null)
            {
                string rootFolder = tmpNode.InnerText.Trim();
                if (rootFolder.Length > 0)
                {
                    if (!Directory.Exists(rootFolder))
                    {
                        MessageBox.Show("Recording Root Folder(" + rootFolder + ") doesn't exist! Please create it first or change it in Options/Basic." + cfgFile);
                        return false;
                    }
                }
                else
                {
                    MessageBox.Show("Recording Root Folder is set to null. Please set it in Options/Basic.");
                    return false;
                }
            }
            else
            {
                MessageBox.Show("Missing AudioRootFolder in XML config file :" + cfgFile);
                return false;
            }

            return true;
        }

        public void StopManageClient()
        {
            timer1.Enabled = false;
            timer2.Enabled = false;

            startRecordingToolStripMenuItem.Enabled = false;
            stopRecordingToolStripMenuItem.Enabled = false;

            toolStripButtonPlay.Enabled = false;
            toolStripButtonStop.Enabled = false;

            //Started = false;
            optionsToolStripMenuItem.Enabled = true;
            optionsToolStripMenuItem1.Enabled = true;
            toolStripButtonOptions.Enabled = true;

            dataGridView1.Enabled = false;

            tbTotalChannels.Enabled = false;
            tbTotalChannels.Text = "";

            tbAvailableChannels.Enabled = false;
            tbAvailableChannels.Text = "";

            tbOfflineChannels.Enabled = false;
            tbOfflineChannels.Text = "";

            tbChannelInUse.Enabled = false;
            tbChannelInUse.Text = "";

            recordingToolStripMenuItem.Text = "Status: Disconnected from server";
            toolStripStatusLabel1.Text = "Status: Disconnected from server";

            openRealtimeListenerToolStripMenuItem.Enabled = false;

            vr_client.Disconnect();

#if SBS_VR
                runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
            runningModelToolStripMenuItem.Enabled = false;
#else
            runningModelToolStripMenuItem.Enabled = true;
#endif

            if (rtPhone != null)
            {
                rtPhone.doClose = true;
                rtPhone.Close();
                rtPhone.Dispose();
                rtPhone = null;

                openRealtimeListenerToolStripMenuItem.Enabled = false;
            }
        }

        public void StopService()
        {
            bool succ = false;

            try
            {
                StopWinService(VR2_Service_Name);
                succ = true;
            }
            catch (Exception ex)
            {
                succ = false;
                MessageBox.Show(ex.ToString());
            }

            if (succ)
            {
                serviceRunning = false;
                timer1.Enabled = false;
                timer2.Enabled = false;

                startRecordingToolStripMenuItem.Enabled = true;
                stopRecordingToolStripMenuItem.Enabled = false;

                toolStripButtonPlay.Enabled = true;
                toolStripButtonStop.Enabled = false;


                //Started = false;
                optionsToolStripMenuItem1.Enabled = true;
                toolStripButtonOptions.Enabled = true;

                dataGridView1.Enabled = false;

                tbTotalChannels.Enabled = false;
                tbTotalChannels.Text = "";

                tbAvailableChannels.Enabled = false;
                tbAvailableChannels.Text = "";

                tbOfflineChannels.Enabled = false;
                tbOfflineChannels.Text = "";

                tbChannelInUse.Enabled = false;
                tbChannelInUse.Text = "";

                recordingToolStripMenuItem.Text = "Status: Recording Service Stopped";
                toolStripStatusLabel1.Text = "Status: Recording Service Stopped";

                openRealtimeListenerToolStripMenuItem.Enabled = false;

#if SBS_VR
                runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
                runningModelToolStripMenuItem.Enabled = false;
#else
                runningModelToolStripMenuItem.Enabled = true;
#endif

                if (rtPhone != null)
                {
                    rtPhone.doClose = true;
                    rtPhone.Close();
                    rtPhone.Dispose();
                    rtPhone = null;

                    openRealtimeListenerToolStripMenuItem.Enabled = false;
                }

            }

        }

        public void StartManageClient()
        {
            startRecordingToolStripMenuItem.Enabled = false;
            stopRecordingToolStripMenuItem.Enabled = false;

            toolStripButtonPlay.Enabled = false;
            toolStripButtonStop.Enabled = false;

            //Started = true;
            optionsToolStripMenuItem.Enabled = true;
            optionsToolStripMenuItem1.Enabled = true;
            toolStripButtonOptions.Enabled = true;

            tbTotalChannels.Enabled = true;
            tbAvailableChannels.Enabled = true;
            tbOfflineChannels.Enabled = true;
            tbChannelInUse.Enabled = true;

            //tbTotalChannels.Text = vr2.ChannelCount.ToString();
            //tbAvailableChannels.Text = vr2.ChannelCount.ToString();
            tbOfflineChannels.Text = "0";
            tbChannelInUse.Text = "";

            recordingToolStripMenuItem.Text = "Status: Running in Manager Client Model";
            toolStripStatusLabel1.Text = "Status: Running in Manager Client Model";

            timer1.Enabled = true;
            timer2.Enabled = true;

#if SBS_VR
                runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
            runningModelToolStripMenuItem.Enabled = false;
#else
            runningModelToolStripMenuItem.Enabled = true;
#endif

            IntPtr resConnect = vr_client.ConnectTo(serverIP, serverPort);

            if (resConnect == IntPtr.Zero)
            {
                //LogoutText("Status: Connected to server");
                vr_client.Disconnect();
            }
            else
            {
                //realtime listener
                XmlElement root = xmlCfg.DocumentElement;
                XmlNode tmpNode = root.SelectSingleNode("//VoiceRecorder/EnableRTSrv");
                if (tmpNode != null)
                {
                    int RTListening = Convert.ToInt32(tmpNode.InnerText);
                    if (RTListening == 1)
                    {
                        rtPhone = new RTListenSoftphone();
                        rtPhone.xmlCfg = xmlCfg;
                        string chanCount = "4";
                        try
                        {
                            tmpNode = root.SelectSingleNode("//VoiceRecorder/ChannelCount");
                            if (tmpNode != null)
                            {
                                chanCount = tmpNode.InnerText.Trim();
                                if (chanCount == "")
                                    chanCount = "4";
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.ToString());
                            chanCount = "4";
                        }
                        rtPhone.MaxChanNum = Convert.ToInt32(chanCount);
                        rtPhone.Show();

                        openRealtimeListenerToolStripMenuItem.Enabled = true;

                    }
                }

            }


        }

        public void StartService()
        {
            event_queue.Clear();

            string xmlFileName = Application.StartupPath + "\\VR2Config.xml";

            if (!StartPreCheck(xmlFileName))
                return;

            bool succ = false;
            try
            {
                StartWinService(VR2_Service_Name);
                succ = true;
            }
            catch (Exception ex)
            {
                succ = false;
                MessageBox.Show(ex.ToString());
            }

            if (succ)
            {
                serviceRunning = true;

                Thread.Sleep(3000);

                startRecordingToolStripMenuItem.Enabled = false;
                stopRecordingToolStripMenuItem.Enabled = true;

                toolStripButtonPlay.Enabled = false;
                toolStripButtonStop.Enabled = true;

                //Started = true;
                optionsToolStripMenuItem.Enabled = false;
                optionsToolStripMenuItem1.Enabled = false;
                toolStripButtonOptions.Enabled = false;

                tbTotalChannels.Enabled = true;
                tbAvailableChannels.Enabled = true;
                tbOfflineChannels.Enabled = true;
                tbChannelInUse.Enabled = true;

                //tbTotalChannels.Text = vr2.ChannelCount.ToString();
                //tbAvailableChannels.Text = vr2.ChannelCount.ToString();
                tbOfflineChannels.Text = "0";
                tbChannelInUse.Text = "";

                timer1.Enabled = true;
                timer2.Enabled = true;

                recordingToolStripMenuItem.Text = "Status: Recording Service Running";
                toolStripStatusLabel1.Text = "Status: Recording Service Running";

#if SBS_VR
                runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
                runningModelToolStripMenuItem.Enabled = false;
#else
                runningModelToolStripMenuItem.Enabled = false;
#endif

                IntPtr resConnect = vr_client.ConnectTo(serverIP, serverPort);

                if (resConnect == IntPtr.Zero)
                {
                    LogoutText("Cannot connect to recorder service!");
                    vr_client.Disconnect();
                }

                //realtime listener
                XmlElement root = xmlCfg.DocumentElement;
                XmlNode tmpNode = root.SelectSingleNode("//VoiceRecorder/EnableRTSrv");
                if (tmpNode != null)
                {
                    int RTListening = Convert.ToInt32(tmpNode.InnerText);
                    if (RTListening == 1)
                    {
                        rtPhone = new RTListenSoftphone();
                        rtPhone.xmlCfg = xmlCfg;
                        string chanCount = "4";
                        try
                        {
                            tmpNode = root.SelectSingleNode("//VoiceRecorder/ChannelCount");
                            if (tmpNode != null)
                            {
                                chanCount = tmpNode.InnerText.Trim();
                                if (chanCount == "")
                                    chanCount = "4";
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.ToString());
                            chanCount = "4";
                        }
                        rtPhone.MaxChanNum = Convert.ToInt32(chanCount);
                        rtPhone.Show();

                        openRealtimeListenerToolStripMenuItem.Enabled = true;

                    }
                }


            }
        }

        public void Start()
        {
            try
            {
                ServiceControllerStatus srvStatus = GetWinServiceStatus(VR2_Service_Name);
                if (srvStatus == System.ServiceProcess.ServiceControllerStatus.Running)
                {
                    MessageBox.Show("The recorder is running as Windows Service in background already! Please stop the service first.", "ERROR");
                    return;
                }
            }
            catch (Exception)
            {
            }

            event_queue.Clear();

            //VRAPIASM.VRAPIEnv.Log(4, "VR2WinApp Form1 Start Place holder 1");

            string xmlFileName = Application.StartupPath + "\\VR2Config.xml";

            if (!StartPreCheck(xmlFileName))
                return;

            vr2 = new VR2Main();
            vr2.m_pCallOffered1 = cbCallOffered;
            vr2.Start(xmlFileName);

            //VRAPIASM.VRAPIEnv.Log(4, "VR2WinApp Form1 Start Place holder 2");

            Thread.Sleep(1000);

            //VRAPIASM.VRAPIEnv.Log(4, "VR2WinApp Form1 Start Place holder 3");

            startRecordingToolStripMenuItem.Enabled = false;
            stopRecordingToolStripMenuItem.Enabled = true;

            toolStripButtonPlay.Enabled = false;
            toolStripButtonStop.Enabled = true;

            //Started = true;
            optionsToolStripMenuItem1.Enabled = false;
            optionsToolStripMenuItem.Enabled = false;
            toolStripButtonOptions.Enabled = false;

            tbTotalChannels.Enabled = true;
            tbAvailableChannels.Enabled = true;
            tbOfflineChannels.Enabled = true;
            tbChannelInUse.Enabled = true;

            ChanNum = vr2.ChannelCount;

            tbTotalChannels.Text = ChanNum.ToString();
            tbAvailableChannels.Text = ChanNum.ToString();
            tbOfflineChannels.Text = "0";
            tbChannelInUse.Text = "";

            if (!dataGridView1.Enabled || dataGridView1.RowCount != vr2.ChannelCount)
            {
                dataGridView1.Enabled = true;

                dataGridView1.DataSource = null;
                dataGridView1.ReadOnly = true;

                dataGridView1.RowCount = ChanNum;
                dataGridView1.ColumnCount = 12;

                //dataGridView1.RowHeadersWidth = 2 * dataGridView1.RowHeadersWidth;

                dataGridView1.RowHeadersWidth = 60;

                dataGridView1.Columns[0].HeaderText = "Status";

                dataGridView1.Columns[1].HeaderText = "Init Time";
                dataGridView1.Columns[2].HeaderText = "Connect Time";
                dataGridView1.Columns[3].HeaderText = "Seconds";

                dataGridView1.Columns[4].HeaderText = "CallerIP";
                dataGridView1.Columns[5].HeaderText = "CallerID";
                dataGridView1.Columns[6].HeaderText = "CalleeIP";
                dataGridView1.Columns[7].HeaderText = "calleeID";
                dataGridView1.Columns[8].HeaderText = "UniqueID";
                dataGridView1.Columns[9].HeaderText = "AudioFile";
                dataGridView1.Columns[10].HeaderText = "Direction";
                dataGridView1.Columns[11].HeaderText = "DTMF";

                //dataGridView1.Rows[0].HeaderCell.OwningColumn.Width = 200;

                for (int i = 0; i < ChanNum; i++)
                {
                    int index = i + 1;
                    dataGridView1.Rows[i].HeaderCell.Value = index.ToString();
                    dataGridView1.Rows[i].Cells[0].Value = "Idle";


                }

            }

            //VRAPIASM.VRAPIEnv.Log(4, "VR2WinApp Form1 Start Place holder 4");

            timer1.Enabled = true;

            recordingToolStripMenuItem.Text = "Status: Recording ...";

            if (vr2.IsLicensed())
                toolStripStatusLabel1.Text = "Status: Recording ...";
            else
                toolStripStatusLabel1.Text = "Status: Recording (NOT Licensed Software. ONLY record first 30 seconds of each call!)";

#if SBS_VR
            runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
            runningModelToolStripMenuItem.Enabled = false;
#else
            runningModelToolStripMenuItem.Enabled = false;
#endif

            //VRAPIASM.VRAPIEnv.Log(4, "VR2WinApp Form1 Start Place holder 5");


            //realtime listener
            XmlElement root = xmlCfg.DocumentElement;
            XmlNode tmpNode = root.SelectSingleNode("//VoiceRecorder/EnableRTSrv");
            if (tmpNode != null)
            {
                int RTListening = Convert.ToInt32(tmpNode.InnerText);
                if (RTListening == 1)
                {
                    rtPhone = new RTListenSoftphone();
                    rtPhone.xmlCfg = xmlCfg;
                    rtPhone.MaxChanNum = ChanNum;
                    rtPhone.Show();

                    openRealtimeListenerToolStripMenuItem.Enabled = true;
                }
            }

            //VRAPIASM.VRAPIEnv.Log(4, "VR2WinApp Form1 Start Place holder 6");
        }

        public void Stop()
        {
            timer1.Enabled = false;

            vr2.Stop();
            vr2 = null;
            startRecordingToolStripMenuItem.Enabled = true;
            stopRecordingToolStripMenuItem.Enabled = false;

            toolStripButtonPlay.Enabled = true;
            toolStripButtonStop.Enabled = false;


            //Started = false;
            optionsToolStripMenuItem.Enabled = true;
            optionsToolStripMenuItem1.Enabled = true;
            toolStripButtonOptions.Enabled = true;

            dataGridView1.Enabled = false;

            tbTotalChannels.Enabled = false;
            tbTotalChannels.Text = "";

            tbAvailableChannels.Enabled = false;
            tbAvailableChannels.Text = "";

            tbOfflineChannels.Enabled = false;
            tbOfflineChannels.Text = "";

            tbChannelInUse.Enabled = false;
            tbChannelInUse.Text = "";

            recordingToolStripMenuItem.Text = "Status: Recording Stopped";
            toolStripStatusLabel1.Text = "Status: Recording Stopped";

#if SBS_VR
            runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
            runningModelToolStripMenuItem.Enabled = false;
#else
            runningModelToolStripMenuItem.Enabled = true;
#endif
            if (rtPhone != null)
            {
                rtPhone.doClose = true;
                rtPhone.Close();
                rtPhone.Dispose();
                rtPhone = null;

                openRealtimeListenerToolStripMenuItem.Enabled = false;

            }

        }

        private void VR2AppMainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!_bExit)
            {
                e.Cancel = true;
                Hide();
                this.ShowInTaskbar = false;

                notifyIcon1.Visible = true;
                notifyIcon1.BalloonTipTitle = VR2_TITLE;
                notifyIcon1.BalloonTipText = "minimized here! double-click to show up.";
                notifyIcon1.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info;
                notifyIcon1.ShowBalloonTip(500);

                if (rtPhone != null)
                    rtPhone.Visible = false;
            }
            else
            {
                if (RunModel == 0)
                {
                    if (vr2 != null)
                    {
                        if (MessageBox.Show("It is recording. Are you sure you want to stop recording and exit?", "Warning", MessageBoxButtons.OKCancel) == DialogResult.OK)
                        {
                            Stop();
                        }
                        else
                        {
                            e.Cancel = true;
                        }
                    }
                }
                else if (RunModel == 1)
                {
                    //doesn't matter, if service is running, let it run. Exit this client side.
                    try
                    {
                        ServiceControllerStatus srvStatus = GetWinServiceStatus(VR2_Service_Name);
                        if (srvStatus == System.ServiceProcess.ServiceControllerStatus.Running)
                        {
                            //just a reminder for service
                            if (MessageBox.Show("Recorder Windows service will be still running and recording after exit!") == DialogResult.OK)
                            {
                            }
                            else
                            {
                            }
                        }
                    }
                    catch (Exception)
                    {

                    }
                }
                else if (RunModel == 2)
                {
                    //
                    StopManageClient();
                }
            }
        }

        private void VR2AppMainForm_Resize(object sender, EventArgs e)
        {
            if (FormWindowState.Minimized == this.WindowState)
            {
                notifyIcon1.BalloonTipTitle = VR2_TITLE;
                notifyIcon1.BalloonTipText = "minimized here! double-click to show up.";
                notifyIcon1.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info;

                notifyIcon1.Visible = true;
                notifyIcon1.ShowBalloonTip(500);
                this.Hide();
                this.ShowInTaskbar = false;

                if (rtPhone != null)
                    rtPhone.Visible = false;
            }
            else if (FormWindowState.Normal == this.WindowState)
            {
                notifyIcon1.Visible = false;
                this.ShowInTaskbar = true;
            }
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            Show();
            this.WindowState = FormWindowState.Normal;

            //this.ShowInTaskbar = true;
            //notifyIcon1.Visible = false;

            if (rtPhone != null)
                rtPhone.Visible = true;
        }

        public int LoadConfigFromXML()
        {
            string xmlFileName = Application.StartupPath + "\\VR2Config.xml";

            if (!File.Exists(xmlFileName))
            {
                xmlFileName = Application.StartupPath + "\\VR2Config-std.xml";
                if (!File.Exists(xmlFileName))
                {
                    MessageBox.Show("Neither VR2Config.xml nor VR2Config-std.xml exists!");
                    return -1;
                }
            }

            xmlCfg = new XmlDocument();
            try
            {
                xmlCfg.Load(xmlFileName);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return -2;
            }

            //XmlElement root = xmlCfg.DocumentElement;

            xmlFileName = Application.StartupPath + "\\VR2Config.xml";

            if (!File.Exists(xmlFileName))
            {
                SaveConfigToXML();
            }

            return 1;
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ReloadXMLCfg(); //Get the latest configuration from file. It may be changed manually by hand.
            VR2Options dlg = new VR2Options();
            dlg.xmlCfg = xmlCfg;
            //dlg.mainForm = this;
            dlg.NICs = NICs;
            dlg.StartRecordingOnBoot = StartRecordingOnBoot;
            dlg.AdminPassword = PasswordProtected;
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                StartRecordingOnBoot = dlg.StartRecordingOnBoot;
                PasswordProtected = dlg.AdminPassword;
                SaveConfigToXML();
            }
        }

        private void toolStripButtonOptions_Click(object sender, EventArgs e)
        {
            optionsToolStripMenuItem_Click(sender, e);
        }

        private void optionsToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            optionsToolStripMenuItem_Click(sender, e);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _bExit = true;
            Close();
        }

        private void quitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            exitToolStripMenuItem_Click(sender, e);
        }

        private void startRecordingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (RunModel == 0)
                Start();
            else if (RunModel == 1)
                StartService();
            else if (RunModel == 2)
                StartManageClient();
        }

        private void toolStripButtonPlay_Click(object sender, EventArgs e)
        {
            startRecordingToolStripMenuItem_Click(sender, e);
        }

        private void stopRecordingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (RunModel == 0)
                Stop();
            else if (RunModel == 1)
                StopService();
            else if (RunModel == 2)
                StopManageClient();
        }

        private void toolStripButtonStop_Click(object sender, EventArgs e)
        {
            stopRecordingToolStripMenuItem_Click(sender, e);
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
#if SBS_VR
            SBSAboutForm frm = new SBSAboutForm();
            frm.ShowDialog();
#elif SmartConnectSystems_VR

#else
            AboutForm frm = new AboutForm();
            frm.ShowDialog();
#endif
        }

        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            aboutToolStripMenuItem_Click(sender, e);
        }

        private void popOutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Show();
            this.WindowState = FormWindowState.Normal;

            if (rtPhone != null)
                rtPhone.Visible = true;
        }

        void SaveConfigToXML()
        {
            RegistryKey regkey;
            //string tmp;
            regkey = Registry.CurrentUser.CreateSubKey(VR2_REG_KEY_ROOT);
            if (regkey == null)
                return;


            regkey.SetValue("PasswordProtected", PasswordProtected);
            regkey.SetValue("RecordOnBoot", StartRecordingOnBoot);

            regkey.Close();

            string xmlFileName = Application.StartupPath + "\\VR2Config.xml";

            try
            {
                xmlCfg.Save(xmlFileName);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (vr2 != null && VR2Main.MainObj != null)
            {
                int chanInUse = 0;

                if (vr2.Channels == null) return;

                lock (VR2Main.MainObj)
                {
                    VR2Channel[] Channels = vr2.Channels;

                    for (int i = 0; i < vr2.ChannelCount; i++)
                    {
                        if (Channels[i].ChanStatus == 0)
                        {
                            dataGridView1.Rows[i].Cells[0].Value = "Idle";
                            dataGridView1.Rows[i].Cells[1].Value = "";
                            dataGridView1.Rows[i].Cells[2].Value = "";
                            dataGridView1.Rows[i].Cells[3].Value = "";


                            dataGridView1.Rows[i].Cells[4].Value = "";
                            dataGridView1.Rows[i].Cells[5].Value = "";
                            dataGridView1.Rows[i].Cells[6].Value = "";
                            dataGridView1.Rows[i].Cells[7].Value = "";
                            dataGridView1.Rows[i].Cells[8].Value = "";
                            dataGridView1.Rows[i].Cells[9].Value = "";
                            dataGridView1.Rows[i].Cells[10].Value = "";
                            dataGridView1.Rows[i].Cells[11].Value = "";
                        }
                        else if (Channels[i].ChanStatus == 1)
                        {
                            dataGridView1.Rows[i].Cells[0].Value = "Ringing";
                            dataGridView1.Rows[i].Cells[1].Value = Channels[i].InitTime.ToString("yyyy-MM-dd HH:mm:ss");
                            dataGridView1.Rows[i].Cells[2].Value = "";
                            dataGridView1.Rows[i].Cells[3].Value = "";
                            chanInUse++;

                            dataGridView1.Rows[i].Cells[4].Value = Channels[i].CallerIP;
                            dataGridView1.Rows[i].Cells[5].Value = Channels[i].CallerID;
                            dataGridView1.Rows[i].Cells[6].Value = Channels[i].CalleeIP;
                            dataGridView1.Rows[i].Cells[7].Value = Channels[i].CalleeID;
                            dataGridView1.Rows[i].Cells[8].Value = Channels[i].UniqueID;
                            dataGridView1.Rows[i].Cells[9].Value = Channels[i].AudioFile;
                            dataGridView1.Rows[i].Cells[10].Value = Channels[i].CallDir == 0 ? "Inbound" : "Outbound";
                            dataGridView1.Rows[i].Cells[11].Value = Channels[i].DTMFStr;
                        }
                        else if (Channels[i].ChanStatus == 2)
                        {
                            dataGridView1.Rows[i].Cells[0].Value = "Connected";
                            dataGridView1.Rows[i].Cells[1].Value = Channels[i].InitTime.ToString("yyyy-MM-dd HH:mm:ss");
                            dataGridView1.Rows[i].Cells[2].Value = Channels[i].ConnectTime.ToString("yyyy-MM-dd HH:mm:ss");
                            TimeSpan sp = DateTime.Now - Channels[i].ConnectTime;
                            int totalSec = Convert.ToInt32(sp.TotalSeconds);
                            dataGridView1.Rows[i].Cells[3].Value = totalSec.ToString();
                            chanInUse++;

                            dataGridView1.Rows[i].Cells[4].Value = Channels[i].CallerIP;
                            dataGridView1.Rows[i].Cells[5].Value = Channels[i].CallerID;
                            dataGridView1.Rows[i].Cells[6].Value = Channels[i].CalleeIP;
                            dataGridView1.Rows[i].Cells[7].Value = Channels[i].CalleeID;
                            dataGridView1.Rows[i].Cells[8].Value = Channels[i].UniqueID;
                            dataGridView1.Rows[i].Cells[9].Value = Channels[i].AudioFile;
                            dataGridView1.Rows[i].Cells[10].Value = Channels[i].CallDir == 0 ? "Inbound" : "Outbound";
                            dataGridView1.Rows[i].Cells[11].Value = Channels[i].DTMFStr;
                        }


                    }
                }

                tbChannelInUse.Text = chanInUse.ToString();

                tbTotalCalls.Text = vr2.totalCallCount.ToString();
                tbConnectedCalls.Text = vr2.connCallCount.ToString();
                //int failedCnt = (vr2.totalCallCount - vr2.connCallCount);
                tbFailedCalls.Text = vr2.failedCallCount.ToString(); //failedCnt.ToString();
            }

            lock (event_queue)
            {
                while (event_queue.Count > 0)
                {
                    VR2Channel chan = event_queue.Dequeue();
                    string callerid = GetSIPAddressInfo(1, chan.CallerID);
                    string calleeid = GetSIPAddressInfo(1, chan.CalleeID);

                    if (callerid.Length > 0 && calleeid.Length > 0)
                    {
                        string msg = "New call from " + callerid + " to " + calleeid;
                        notifyIcon1.BalloonTipTitle = VR2_TITLE;
                        notifyIcon1.BalloonTipText = msg;
                        notifyIcon1.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info;

                        notifyIcon1.Visible = true;
                        notifyIcon1.ShowBalloonTip(1000);
                    }

                    //toolStripStatusLabel1.Text = "Status: " + msg;
                    //LogoutText("OnCallOffered event arrived. caller:" + chan.CallerID + " called:" + chan.CalleeID + " call dir: " + chan.CallDir.ToString() + " file: " + chan.AudioFile);
                    LogoutText(callerid + "=>" + calleeid);
                }
            }
        }

        public static string GetSIPAddressInfo(int flag, string sipAddr)
        {
            //some memory problem with this one
            /*
             X [2009-04-21 11:58:43] *************On_ProxyNewCallSession got exception: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
             X [2009-04-21 11:58:43] System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
             at GTAPIASM.GTAPIEnv.GTAPI_GetSIPAddressInfo(Int32 flag, String sipAddr)
             at GTAPIASM.GTAPIEnv.GetSIPAddressInfo(Int32 flag, String sipAddr) in C:\TEMP\projects\Samples\GTAPIASM\GTAPIASM\GTAPIEnv.cs:line 821
             at GTSIPPBX.SIPPBX.getExtensionBySIPAddr(String sip_addr)
             at GTSIPPBX.GTSIPPBXEnv.On_ProxyNewCallSession(UInt32 pid, UInt32 sid, UInt32 msg, String fromid, String toid, String suri, String via, String saddr, UInt16 nport, Boolean bCredit)
             */
            //return string.Copy(GTAPI_GetSIPAddressInfo(flag, sipAddr));

            if (sipAddr == null)
                return "";

            if (sipAddr.Length == 0)
                return "";

            //a fix for google andriod phone bad implementation
            if (sipAddr.IndexOf("<sip:") == -1 && sipAddr.IndexOf("sip:") >= 0)
            {
                int idx1 = sipAddr.IndexOf("sip:");
                if (idx1 == 0)
                {
                    sipAddr = "<" + sipAddr + ">";
                }
                else
                {
                    sipAddr = sipAddr.Substring(0, idx1) + "<" + sipAddr.Substring(idx1) + ">";
                }
            }

            int nPos = 0;
            int nPos1 = 0;

            if (flag == 0) //display name
            {
                nPos = sipAddr.IndexOf("<sip:");
                if (nPos == -1 || nPos == 0)
                    return "";
                else
                    return sipAddr.Substring(0, nPos);
            }
            else if (flag == 1) //user name
            {
                nPos = sipAddr.IndexOf("<sip:");
                if (nPos == -1)
                    return "";
                else
                {
                    nPos += 5;

                    nPos1 = sipAddr.IndexOf('@', nPos);
                    if (nPos1 == -1)
                        return "";
                    else
                        return sipAddr.Substring(nPos, nPos1 - nPos);
                }
            }
            else if (flag == 2) //ip address
            {
                nPos = sipAddr.IndexOf('@');
                if (nPos == -1)
                {
                    nPos = sipAddr.IndexOf("<sip:");
                    if (nPos == -1)
                        return "";
                    else
                        nPos += 5;
                }
                else
                    nPos += 1;

                nPos1 = sipAddr.IndexOf('>', nPos);

                string ipAddr = "";

                if (nPos1 == -1)
                    ipAddr = sipAddr.Substring(nPos);
                else
                    ipAddr = sipAddr.Substring(nPos, nPos1 - nPos);

                nPos = ipAddr.IndexOf(';');
                if (nPos != -1)
                    ipAddr = ipAddr.Substring(0, nPos);

                nPos = ipAddr.IndexOf(':');
                if (nPos != -1)
                    ipAddr = ipAddr.Substring(0, nPos);

                return ipAddr;
            }
            else if (flag == 3) //port
            {
                nPos = sipAddr.IndexOf('@');
                if (nPos == -1)
                {
                    nPos = sipAddr.IndexOf("<sip:");
                    if (nPos == -1)
                        return "";
                    else
                        nPos += 5;
                }
                else
                    nPos += 1;

                nPos1 = sipAddr.IndexOf('>', nPos);

                string ipAddr = "";

                if (nPos1 == -1)
                    ipAddr = sipAddr.Substring(nPos);
                else
                    ipAddr = sipAddr.Substring(nPos, nPos1 - nPos);

                nPos = ipAddr.IndexOf(';');
                if (nPos != -1)
                    ipAddr = ipAddr.Substring(0, nPos);

                nPos = ipAddr.IndexOf(':');
                if (nPos == -1)
                    ipAddr = "";
                else
                    ipAddr = ipAddr.Substring(nPos + 1);

                return ipAddr;
            }

            return "";
        }

        public static int cbCallOffered(int ChanIndex, string CallerIP, string CallerID, string CalleeIP, string CalleeID, uint CallTime, string UniqueID, string AudioFile, int CallDir)
        {
            VR2Channel chan = new VR2Channel();

            chan.ChanIndex = ChanIndex;
            chan.CallerIP = CallerIP;
            chan.CallerID = CallerID;
            chan.CalleeIP = CalleeIP;
            chan.CalleeID = CalleeID;
            chan.UniqueID = UniqueID;
            chan.AudioFile = AudioFile;
            chan.CallDir = CallDir;
            chan.InitTime = DateTime.Now;
            //chan.ConnectTime = DateTime.Now;
            //chan.EndTime = DateTime.Now;

            lock (main_form.event_queue)
            {
                main_form.event_queue.Enqueue(chan);
            }

            return 0;

        }

        private void toolStripButtonSearch_Click(object sender, EventArgs e)
        {
            PerformQuickSearch();
        }

        private void quickSearchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PerformQuickSearch();
        }

        public void PerformQuickSearch()
        {
            DBServerSetting db_set = null;

            XmlElement root = xmlCfg.DocumentElement;

            XmlNode tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/Enabled");
            if (tmpNode != null)
            {
                if (VR2.VR2Main.GetBooleanFromXMLNode(tmpNode))
                {
                    db_set = new DBServerSetting();

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/DBType");
                    if (tmpNode != null)
                        db_set.dbType = Convert.ToInt32(tmpNode.InnerText);

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/DBServer");
                    if (tmpNode != null)
                        db_set.sDBServer = tmpNode.InnerText;

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/DBName");
                    if (tmpNode != null)
                        db_set.sDBName = tmpNode.InnerText;

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/AuthType");
                    if (tmpNode != null)
                        db_set.authType = Convert.ToInt32(tmpNode.InnerText);

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/UserName");
                    if (tmpNode != null)
                        db_set.sUserName = tmpNode.InnerText;

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/Password");
                    if (tmpNode != null)
                        db_set.sPassword = tmpNode.InnerText;

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/CallLogTableName");
                    if (tmpNode != null)
                    {
                        if (tmpNode.InnerText.Length > 0)
                            db_set.CallLogTableName = tmpNode.InnerText;
                    }

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/ChannelStatusTableName");
                    if (tmpNode != null)
                    {
                        if (tmpNode.InnerText.Length > 0)
                            db_set.ChannelStatusTableName = tmpNode.InnerText;
                    }

                }
                else
                {
                    MessageBox.Show("Please enable database setting in Options/Database.");
                    return;
                }
            }
            else
            {
                MessageBox.Show("Please enable database setting in Options/Database.");
                return;
            }

            if (db_set != null)
            {
                if (db_set.ConnectDB())
                {
                    db_set.TestTables();

                    //update channel status if possible
                    //catCMD.CommandText = "CREATE TABLE " + ChannelStatusTableName + "(ChanID SmallInt, CallerIP varchar(80) NULL, CallerID varchar(80) NULL, CalleeIP varchar(80) NULL, CalleeID varchar(80) NULL, TimeInit datetime NULL, TimeBegin datetime NULL, TimeEnd datetime NULL, UniqueID varchar(150) NULL, RecordPath varchar(250) NULL, DIR TINYINT, CallConnected TINYINT, ChanStatus TINYINT)";

                    db_set.DisconnectDB();
                }
                else
                {
                    MessageBox.Show("Cannot access database. Please check database setting in Options/Database.");
                    return;
                }
            }
            else
            {
                MessageBox.Show("Please enable database setting in Options/Database.");
                return;
            }


            QuickSearch sr = new QuickSearch();
            sr.db_set = db_set;
            sr.ShowDialog();
        }

        private void complexSearchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DBServerSetting db_set = null;
            int MaxChanNum = 4;

            XmlElement root = xmlCfg.DocumentElement;

            XmlNode tmpNode = root.SelectSingleNode("//VoiceRecorder/ChannelCount");
            if (tmpNode != null)
            {
                MaxChanNum = Convert.ToInt32(tmpNode.InnerText.Trim());
            }

            tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/Enabled");
            if (tmpNode != null)
            {
                if (VR2.VR2Main.GetBooleanFromXMLNode(tmpNode))
                {
                    db_set = new DBServerSetting();

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/DBType");
                    if (tmpNode != null)
                        db_set.dbType = Convert.ToInt32(tmpNode.InnerText);

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/DBServer");
                    if (tmpNode != null)
                        db_set.sDBServer = tmpNode.InnerText;

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/DBName");
                    if (tmpNode != null)
                        db_set.sDBName = tmpNode.InnerText;

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/AuthType");
                    if (tmpNode != null)
                        db_set.authType = Convert.ToInt32(tmpNode.InnerText);

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/UserName");
                    if (tmpNode != null)
                        db_set.sUserName = tmpNode.InnerText;

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/Password");
                    if (tmpNode != null)
                        db_set.sPassword = tmpNode.InnerText;

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/CallLogTableName");
                    if (tmpNode != null)
                    {
                        if (tmpNode.InnerText.Length > 0)
                            db_set.CallLogTableName = tmpNode.InnerText;
                    }

                    tmpNode = root.SelectSingleNode("//VoiceRecorder/Database/ChannelStatusTableName");
                    if (tmpNode != null)
                    {
                        if (tmpNode.InnerText.Length > 0)
                            db_set.ChannelStatusTableName = tmpNode.InnerText;
                    }

                }
                else
                {
                    MessageBox.Show("Please enable database setting in Options/Database.");
                    return;
                }
            }
            else
            {
                MessageBox.Show("Please enable database setting in Options/Database.");
                return;
            }

            if (db_set != null)
            {
                if (db_set.ConnectDB())
                {
                    db_set.TestTables();

                    //update channel status if possible
                    //catCMD.CommandText = "CREATE TABLE " + ChannelStatusTableName + "(ChanID SmallInt, CallerIP varchar(80) NULL, CallerID varchar(80) NULL, CalleeIP varchar(80) NULL, CalleeID varchar(80) NULL, TimeInit datetime NULL, TimeBegin datetime NULL, TimeEnd datetime NULL, UniqueID varchar(150) NULL, RecordPath varchar(250) NULL, DIR TINYINT, CallConnected TINYINT, ChanStatus TINYINT)";

                    db_set.DisconnectDB();
                }
                else
                {
                    MessageBox.Show("Cannot access database. Please check database setting in Options/Database.");
                    return;
                }
            }
            else
            {
                MessageBox.Show("Please enable database setting in Options/Database.");
                return;
            }

            ComplexSearch sr = new ComplexSearch();
            sr.db_set = db_set;
            sr.maxChanNum = MaxChanNum;
            sr.ShowDialog();
        }

        public void ServerConnected(bool bConnected)
        {
            /*
                        if (bConnected)
                        {
                            btnConnect.Enabled = false;
                            btnDisconnect.Enabled = true;
                        }
                        else
                        {
                            btnConnect.Enabled = true;
                            btnDisconnect.Enabled = false;
                        }
             */
            serverConnected = bConnected;
            if (!bConnected)
            {
                dataGridView1.Enabled = false;
                LogoutText("Lost connection to server");
                //connectToolStripMenuItem.Enabled = true;
                //disconnectToolStripMenuItem.Enabled = false;

                if (RunModel == 2)
                {
                    recordingToolStripMenuItem.Text = "Status: No connection to server";
                    toolStripStatusLabel1.Text = "Status: No connection to server";
                }
            }
            else
            {
                LogoutText("Connected To Server " + serverIP + ":" + serverPort.ToString());
                vr_client.GetStatus("general");
                waiting_general = true;
                //connectToolStripMenuItem.Enabled = false;
                //disconnectToolStripMenuItem.Enabled = true;

                if (RunModel == 2)
                {
                    recordingToolStripMenuItem.Text = "Status: Connected To Server " + serverIP + ":" + serverPort.ToString();
                    toolStripStatusLabel1.Text = "Status: Connected To Server " + serverIP + ":" + serverPort.ToString();
                }
            }
        }

        public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
        {
            // Unix timestamp is seconds past epoch
            System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
            dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
            return dtDateTime;
        }

        public static double DateTimeToUnixTimestamp(DateTime dateTime)
        {
            return (dateTime - new DateTime(1970, 1, 1).ToLocalTime()).TotalSeconds;
        }

        //Recorder VR2 Client Events
        public void Recorder_OnCallOffered(int ChanIndex, string CallerIP, string CallerID, string CalleeIP, string CalleeID, uint CallTime, string UniqueID, string AudioFile, int CallDir)
        {
            //LogoutText("OnCallOffered event arrived. caller:" + CallerID + " called:" + CalleeID + " call dir: " + CallDir.ToString() + " file: " + AudioFile);

            VR2Channel chan = new VR2Channel();

            chan.ChanIndex = ChanIndex;
            chan.CallerIP = CallerIP;
            chan.CallerID = CallerID;
            chan.CalleeIP = CalleeIP;
            chan.CalleeID = CalleeID;
            chan.UniqueID = UniqueID;
            chan.AudioFile = AudioFile;
            chan.CallDir = CallDir;
            chan.InitTime = DateTime.Now;
            //chan.ConnectTime = DateTime.Now;
            //chan.EndTime = DateTime.Now;

            lock (main_form.event_queue)
            {
                main_form.event_queue.Enqueue(chan);
            }

            DateTime initTime = UnixTimeStampToDateTime(Convert.ToDouble(CallTime));

            try
            {
                //if (DataViewType == 0)
                {
                    dataGridView1.Rows[ChanIndex].Cells[0].Value = "Ringing";

                    dataGridView1.Rows[ChanIndex].Cells[1].Value = initTime.ToString("yyyy-MM-dd HH:mm:ss");
                    dataGridView1.Rows[ChanIndex].Cells[2].Value = "";
                    dataGridView1.Rows[ChanIndex].Cells[3].Value = "";

                    dataGridView1.Rows[ChanIndex].Cells[4].Value = CallerIP;
                    dataGridView1.Rows[ChanIndex].Cells[5].Value = CallerID;
                    dataGridView1.Rows[ChanIndex].Cells[6].Value = CalleeIP;
                    dataGridView1.Rows[ChanIndex].Cells[7].Value = CalleeID;
                    dataGridView1.Rows[ChanIndex].Cells[8].Value = UniqueID;
                    dataGridView1.Rows[ChanIndex].Cells[9].Value = AudioFile;
                    dataGridView1.Rows[ChanIndex].Cells[10].Value = CallDir == 0 ? "Inbound" : "Outbound";
                }
            }
            catch (Exception)
            {
            }

        }

        public void Recorder_OnCallConnected(int ChanIndex, string CallerIP, string CallerID, string CalleeIP, string CalleeID, uint InitTime, uint ConnectTime, string UniqueID, string AudioFile, int CallDir)
        {
            //LogoutText("OnCallConnected event arrived. caller:" + CallerID + " called:" + CalleeID + " call dir: " + CallDir.ToString() + " file: " + AudioFile);

            DateTime initTime = UnixTimeStampToDateTime(Convert.ToDouble(InitTime));
            DateTime connTime = UnixTimeStampToDateTime(Convert.ToDouble(ConnectTime));

            try
            {
                //if (DataViewType == 0)
                {
                    dataGridView1.Rows[ChanIndex].Cells[0].Value = "Recording";

                    dataGridView1.Rows[ChanIndex].Cells[1].Value = initTime.ToString("yyyy-MM-dd HH:mm:ss"); ;
                    dataGridView1.Rows[ChanIndex].Cells[2].Value = connTime.ToString("yyyy-MM-dd HH:mm:ss"); ;
                    dataGridView1.Rows[ChanIndex].Cells[3].Value = "0";

                    dataGridView1.Rows[ChanIndex].Cells[4].Value = CallerIP;
                    dataGridView1.Rows[ChanIndex].Cells[5].Value = CallerID;
                    dataGridView1.Rows[ChanIndex].Cells[6].Value = CalleeIP;
                    dataGridView1.Rows[ChanIndex].Cells[7].Value = CalleeID;
                    dataGridView1.Rows[ChanIndex].Cells[8].Value = UniqueID;
                    dataGridView1.Rows[ChanIndex].Cells[9].Value = AudioFile;
                    dataGridView1.Rows[ChanIndex].Cells[10].Value = CallDir == 0 ? "Inbound" : "Outbound";
                }
            }
            catch (Exception)
            {
            }
        }

        public void Recorder_OnCallIdle(int ChanIndex, string CallerIP, string CallerID, string CalleeIP, string CalleeID, uint InitTime, uint ConnectTime, uint EndTime, string UniqueID, string AudioFile, int AudioFileNum, int Reason, int CallDir, string DTMFStr)
        {
            //LogoutText("OnCallIdle event arrived. caller:" + CallerID + " called:" + CalleeID + " call dir: " + CallDir.ToString() + " file: " + AudioFile);

            DateTime initTime = UnixTimeStampToDateTime(Convert.ToDouble(InitTime));
            DateTime connTime = UnixTimeStampToDateTime(Convert.ToDouble(ConnectTime));
            DateTime endTime = UnixTimeStampToDateTime(Convert.ToDouble(EndTime));

            try
            {
                //if (DataViewType == 0)
                {
                    dataGridView1.Rows[ChanIndex].Cells[0].Value = "Idle";

                    dataGridView1.Rows[ChanIndex].Cells[1].Value = "";
                    dataGridView1.Rows[ChanIndex].Cells[2].Value = "";
                    dataGridView1.Rows[ChanIndex].Cells[3].Value = "";


                    //dataGridView1.Rows[ChanIndex].Cells[1].Value = CallerIP;
                    //dataGridView1.Rows[ChanIndex].Cells[2].Value = CallerID;
                    //dataGridView1.Rows[ChanIndex].Cells[3].Value = CalleeIP;
                    //dataGridView1.Rows[ChanIndex].Cells[4].Value = CalleeID;
                    //dataGridView1.Rows[ChanIndex].Cells[5].Value = UniqueID;
                    //dataGridView1.Rows[ChanIndex].Cells[6].Value = AudioFile;
                    //dataGridView1.Rows[ChanIndex].Cells[7].Value = CallDir == 0 ? "Inbound" : "Outbound";
                    //dataGridView1.Rows[ChanIndex].Cells[8].Value = DTMFStr;

                    dataGridView1.Rows[ChanIndex].Cells[4].Value = "";
                    dataGridView1.Rows[ChanIndex].Cells[5].Value = "";
                    dataGridView1.Rows[ChanIndex].Cells[6].Value = "";
                    dataGridView1.Rows[ChanIndex].Cells[7].Value = "";
                    dataGridView1.Rows[ChanIndex].Cells[8].Value = "";
                    dataGridView1.Rows[ChanIndex].Cells[9].Value = "";
                    dataGridView1.Rows[ChanIndex].Cells[10].Value = "";
                    dataGridView1.Rows[ChanIndex].Cells[11].Value = "";
                }
            }
            catch (Exception)
            {
            }
        }

        public void Recorder_OnCallInfo(int ChanIndex, string CallerIP, string CallerID, string CalleeIP, string CalleeID, string UniqueID, string AudioFile, int CallDir)
        {
            //LogoutText("OnCallInfo event arrived. caller:" + CallerID + " called:" + CalleeID + " call dir: " + CallDir.ToString() + " file: " + AudioFile);
            try
            {
                //if (DataViewType == 0)
                {
                    dataGridView1.Rows[ChanIndex].Cells[4].Value = CallerIP;
                    dataGridView1.Rows[ChanIndex].Cells[5].Value = CallerID;
                    dataGridView1.Rows[ChanIndex].Cells[6].Value = CalleeIP;
                    dataGridView1.Rows[ChanIndex].Cells[7].Value = CalleeID;
                    dataGridView1.Rows[ChanIndex].Cells[8].Value = UniqueID;
                    dataGridView1.Rows[ChanIndex].Cells[9].Value = AudioFile;
                    dataGridView1.Rows[ChanIndex].Cells[10].Value = CallDir == 0 ? "Inbound" : "Outbound";
                }
            }
            catch (Exception)
            {
            }
        }

        public void Recorder_OnStatusChannel(VR2Channel chan)
        {
            //LogoutText("Channel " + chan.ChanIndex.ToString() + " status arrived");

            try
            {
                //if (DataViewType == 0)
                {
                    if (chan.ChanStatus == 0)
                    {
                        dataGridView1.Rows[chan.ChanIndex].Cells[0].Value = "Idle";
                        dataGridView1.Rows[chan.ChanIndex].Cells[1].Value = "";
                        dataGridView1.Rows[chan.ChanIndex].Cells[2].Value = "";
                        dataGridView1.Rows[chan.ChanIndex].Cells[3].Value = "";

                        dataGridView1.Rows[chan.ChanIndex].Cells[4].Value = "";
                        dataGridView1.Rows[chan.ChanIndex].Cells[5].Value = "";
                        dataGridView1.Rows[chan.ChanIndex].Cells[6].Value = "";

                        dataGridView1.Rows[chan.ChanIndex].Cells[7].Value = "";
                        dataGridView1.Rows[chan.ChanIndex].Cells[8].Value = "";
                        dataGridView1.Rows[chan.ChanIndex].Cells[9].Value = "";
                        dataGridView1.Rows[chan.ChanIndex].Cells[10].Value = "";
                        dataGridView1.Rows[chan.ChanIndex].Cells[11].Value = "";
                    }
                    else if (chan.ChanStatus == 1)
                    {
                        dataGridView1.Rows[chan.ChanIndex].Cells[0].Value = "Ringing";
                        dataGridView1.Rows[chan.ChanIndex].Cells[1].Value = chan.InitTime.ToString("yyyy-MM-dd HH:mm:ss");
                        dataGridView1.Rows[chan.ChanIndex].Cells[2].Value = "";
                        dataGridView1.Rows[chan.ChanIndex].Cells[3].Value = "";

                        dataGridView1.Rows[chan.ChanIndex].Cells[4].Value = chan.CallerIP;
                        dataGridView1.Rows[chan.ChanIndex].Cells[5].Value = chan.CallerID;
                        dataGridView1.Rows[chan.ChanIndex].Cells[6].Value = chan.CalleeIP;
                        dataGridView1.Rows[chan.ChanIndex].Cells[7].Value = chan.CalleeID;
                        dataGridView1.Rows[chan.ChanIndex].Cells[8].Value = chan.UniqueID;
                        dataGridView1.Rows[chan.ChanIndex].Cells[9].Value = chan.AudioFile;
                        dataGridView1.Rows[chan.ChanIndex].Cells[10].Value = chan.CallDir == 0 ? "Inbound" : "Outbound";
                        dataGridView1.Rows[chan.ChanIndex].Cells[11].Value = chan.DTMFStr;
                    }
                    else if (chan.ChanStatus == 2)
                    {
                        dataGridView1.Rows[chan.ChanIndex].Cells[0].Value = "Recording";

                        TimeSpan ts = DateTime.Now - chan.ConnectTime;
                        int sec = Convert.ToInt32(ts.TotalSeconds);
                        dataGridView1.Rows[chan.ChanIndex].Cells[1].Value = chan.InitTime.ToString("yyyy-MM-dd HH:mm:ss");
                        dataGridView1.Rows[chan.ChanIndex].Cells[2].Value = chan.ConnectTime.ToString("yyyy-MM-dd HH:mm:ss");
                        dataGridView1.Rows[chan.ChanIndex].Cells[3].Value = sec.ToString();

                        dataGridView1.Rows[chan.ChanIndex].Cells[4].Value = chan.CallerIP;
                        dataGridView1.Rows[chan.ChanIndex].Cells[5].Value = chan.CallerID;
                        dataGridView1.Rows[chan.ChanIndex].Cells[6].Value = chan.CalleeIP;
                        dataGridView1.Rows[chan.ChanIndex].Cells[7].Value = chan.CalleeID;
                        dataGridView1.Rows[chan.ChanIndex].Cells[8].Value = chan.UniqueID;
                        dataGridView1.Rows[chan.ChanIndex].Cells[9].Value = chan.AudioFile;
                        dataGridView1.Rows[chan.ChanIndex].Cells[10].Value = chan.CallDir == 0 ? "Inbound" : "Outbound";
                        dataGridView1.Rows[chan.ChanIndex].Cells[11].Value = chan.DTMFStr;
                    }

                }
            }
            catch (Exception ex)
            {
                LogoutText(ex.ToString());
            }
        }

        public void Recorder_OnCallDTMF(int ChanIndex, string KeyPressed, string DTMFStr)
        {
            try
            {
                //if (DataViewType == 0)
                {
                    dataGridView1.Rows[ChanIndex].Cells[11].Value = DTMFStr;
                }
            }
            catch (Exception)
            {
            }
        }


        public void Recorder_OnStatusGeneral(string[] members)
        {
            int availableChannelNum = 0;
            int inuseChannelNum = 0;
            int chStatus = 0;

            try
            {
                if (members.Length > 0)
                {
                    //first arg is total number of channels
                    ChanNum = Convert.ToInt32(members[0]);
                    tbAvailableChannels.Text = tbTotalChannels.Text = ChanNum.ToString();
                    tbOfflineChannels.Text = "0";

                    if (!dataGridView1.Enabled || dataGridView1.RowCount != ChanNum)
                    {
                        dataGridView1.Enabled = true;

                        dataGridView1.DataSource = null;
                        dataGridView1.ReadOnly = true;

                        dataGridView1.RowCount = ChanNum;
                        dataGridView1.ColumnCount = 12;

                        dataGridView1.Columns[0].HeaderText = "Status";

                        dataGridView1.Columns[1].HeaderText = "Init Time";
                        dataGridView1.Columns[2].HeaderText = "Connect Time";
                        dataGridView1.Columns[3].HeaderText = "Seconds";

                        dataGridView1.Columns[4].HeaderText = "CallerIP";
                        dataGridView1.Columns[5].HeaderText = "CallerID";
                        dataGridView1.Columns[6].HeaderText = "CalleeIP";
                        dataGridView1.Columns[7].HeaderText = "calleeID";
                        dataGridView1.Columns[8].HeaderText = "UniqueID";
                        dataGridView1.Columns[9].HeaderText = "AudioFile";
                        dataGridView1.Columns[10].HeaderText = "Direction";
                        dataGridView1.Columns[11].HeaderText = "DTMF";

                        //dataGridView1.Rows[0].HeaderCell.OwningColumn.Width = 200;

                        for (int i = 0; i < ChanNum; i++)
                        {
                            int index = i + 1;
                            dataGridView1.Rows[i].HeaderCell.Value = index.ToString();
                            dataGridView1.Rows[i].Cells[0].Value = "Idle";
                        }

                    }
                    /*
                    if (RTListening == 1)
                    {
                        if (cbChanID.Items.Count != MaxChanNum && MaxChanNum > 0)
                        {
                            cbChanID.Items.Clear();
                            for (int i = 1; i <= MaxChanNum; i++)
                            {
                                cbChanID.Items.Add(i.ToString());
                            }

                            cbChanID.SelectedIndex = 0;
                            lbRTChanStatus.Text = "Idle";
                        }
                    }*/
                }
                if (members.Length > 1)
                {
                    //second arg is total number of channels which is available(not offline)
                    tbTotalCalls.Text = members[1];
                }
                else
                {
                    //tbAvailableChannels.Text = MaxChanNum.ToString();
                }

                if (members.Length > 2)
                {
                    //second arg is total number of channels which is offline
                    tbConnectedCalls.Text = members[2];

                    tbFailedCalls.Text = Convert.ToString(Convert.ToInt32(members[1]) - Convert.ToInt32(members[2]));
                }
                else
                {
                    tbOfflineChannels.Text = "0";
                }

                if (members.Length > 3)
                {
                    for (int i = 0; i < ChanNum; i++)
                    {
                        chStatus = Convert.ToInt32(members[3 + i]);
                        if (chStatus == -1)
                        {
                            dataGridView1.Rows[i].Cells[0].Value = "Offline";
                        }
                        else if (chStatus == 0)
                        {
                            //if(dataGridView1.Rows[i].Cells[0].Value == "Offline")
                            dataGridView1.Rows[i].Cells[0].Value = "Idle";
                            availableChannelNum++;
                        }
                        else if (chStatus == 1)
                        {
                            dataGridView1.Rows[i].Cells[0].Value = "Ringing";
                            availableChannelNum++;
                            inuseChannelNum++;

                            vr_client.GetStatus("channel " + i.ToString());
                        }
                        else if (chStatus == 2)
                        {
                            dataGridView1.Rows[i].Cells[0].Value = "Recording";
                            availableChannelNum++;
                            inuseChannelNum++;

                            vr_client.GetStatus("channel " + i.ToString());
                        }
                    }

                    tbAvailableChannels.Text = availableChannelNum.ToString();
                    tbChannelInUse.Text = inuseChannelNum.ToString();
                    tbOfflineChannels.Text = Convert.ToString(ChanNum - availableChannelNum);
                }
            }
            catch (Exception ex)
            {
                LogoutText(ex.ToString());
            }

            waiting_general = false;
        }

        public void LogoutText(string sLogInfo/*, bool bTrace*/)
        {
            lock (this)
            {
                sLogInfo = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]" + " " + sLogInfo;
                if (richTextBox1.Text.Length > 1024 * 512)
                    richTextBox1.Text = "";
                richTextBox1.Text = richTextBox1.Text + sLogInfo + "\r\n";
                richTextBox1.Select(richTextBox1.Text.Length - 2, 1);
                richTextBox1.ScrollToCaret();
            }
        }

        public bool ReloadXMLCfg()
        {
            string xmlFileName = Application.StartupPath + "\\VR2Config.xml";
            if (xmlCfg != null)
            {
                xmlCfg.RemoveAll();
                xmlCfg = null;
            }

            xmlCfg = new XmlDocument();
            try
            {
                xmlCfg.Load(xmlFileName);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return false;
            }

            return true;
        }


        public static ServiceControllerStatus GetWinServiceStatus(string strServiceName)
        {
            ServiceController service = new ServiceController(strServiceName);
            ServiceControllerStatus status = service.Status;
            service.Dispose();
            return status;
        }

        //[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        public static void StartWinService(string strServiceName)
        {
            ServiceController service = null;

            try
            {
                service = new ServiceController(strServiceName);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

            if (service != null)
            {
                service.Start();
                service.Dispose();
            }
        }

        //[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
        public static void StopWinService(string strServiceName)
        {
            ServiceController service = null;

            try
            {
                service = new ServiceController(strServiceName);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

            if (service != null)
            {
                service.Stop();
                service.Dispose();
            }
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            try
            {
                /*
                if (env != null)
                {
                    env.ProcessGTAPIEvent();
                }*/

                if (vr_client != null)
                {
                    vr_client.ProcessEvents();
                }
            }
            catch (Exception ex)
            {
                LogoutText(ex.ToString());
            }

            timerCount++;

            if (timerCount % 5 == 0) //every second
            {
                /*
                if (dataGridView1.Enabled && dataGridView1.RowCount == ChanNum && ChanNum > 0)
                {
                    for (int i = 0; i < ChanNum; i++)
                    {
                        if (dataGridView1.Rows[i].Cells[2].Value != null)
                        {
                            string s = dataGridView1.Rows[i].Cells[2].Value.ToString();
                            if (s.Length > 0)
                            {
                                TimeSpan sp = DateTime.Now - VR2.VR2Main.GetDotNetDateTime(s);
                                int sec = Convert.ToInt32(sp.TotalSeconds);
                                dataGridView1.Rows[i].Cells[3].Value = sec.ToString();
                            }
                        }
                    }
                    
                }*/
            }
            if (timerCount % 10 == 0) //every 2 seconds
            {
                if (vr_client != null && !waiting_general && serverConnected)
                {
                    vr_client.GetStatus("general");
                    waiting_general = true;
                }
            }
            if (timerCount % 25 == 0) //every 5 seconds
            {
            }
            if (timerCount % 50 == 0) //every 10 seconds
            {
            }

            if (timerCount == 300)
                timerCount = 0; //reset to 0
        }

        private void runningModelToolStripMenuItem_Click(object sender, EventArgs e)
        {
#if SBS_VR
#elif SmartConnectSystems_VR
#else
            RegistryKey regkey = Registry.CurrentUser.CreateSubKey(VR2_REG_KEY_ROOT);
            if (regkey == null)
                return;

            //object is null, it is the first running, need to ask
            RunningModel dlg = new RunningModel();
            dlg.RunModel = RunModel;
            dlg.ServerIP = serverIP;
            dlg.ServerPort = serverPort;
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                if (RunModel == 2)
                {
                    //original runModel is manager client
                    //disconnect first.
                    StopManageClient();
                }

                RunModel = dlg.RunModel;
                serverIP = dlg.ServerIP;
                serverPort = dlg.ServerPort;
                if (serverIP.Length == 0)
                    serverIP = "127.0.0.1";

                regkey.SetValue("RunModel", RunModel);
                regkey.SetValue("ServerIP", serverIP);
                int port = serverPort;
                regkey.SetValue("ServerPort", port);
            }

            regkey.Close();

            if (RunModel == 0)
            {
                startRecordingToolStripMenuItem.Enabled = true;
                stopRecordingToolStripMenuItem.Enabled = false;

                toolStripButtonPlay.Enabled = true;
                toolStripButtonStop.Enabled = false;

                recordingToolStripMenuItem.Text = "Status: Recording Stopped";
                toolStripStatusLabel1.Text = "Status: Recording Stopped";
            }
            else if (RunModel == 1)
            {
                //service model
                try
                {
                    ServiceControllerStatus srvStatus = GetWinServiceStatus(VR2_Service_Name);
                    if (srvStatus == System.ServiceProcess.ServiceControllerStatus.Stopped)
                    {
                        serviceRunning = false;
                        timer1.Enabled = false;
                        timer2.Enabled = false;

                        startRecordingToolStripMenuItem.Enabled = true;
                        stopRecordingToolStripMenuItem.Enabled = false;

                        toolStripButtonPlay.Enabled = true;
                        toolStripButtonStop.Enabled = false;


                        //Started = false;
                        optionsToolStripMenuItem1.Enabled = true;
                        toolStripButtonOptions.Enabled = true;

                        dataGridView1.Enabled = false;

                        tbTotalChannels.Enabled = false;
                        tbTotalChannels.Text = "";

                        tbAvailableChannels.Enabled = false;
                        tbAvailableChannels.Text = "";

                        tbOfflineChannels.Enabled = false;
                        tbOfflineChannels.Text = "";

                        tbChannelInUse.Enabled = false;
                        tbChannelInUse.Text = "";

                        recordingToolStripMenuItem.Text = "Status: Recording Service Stopped";
                        toolStripStatusLabel1.Text = "Status: Recording Service Stopped";

#if SBS_VR
                        runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
                        runningModelToolStripMenuItem.Enabled = false;
#else
                        runningModelToolStripMenuItem.Enabled = true;
#endif
                    }
                    else if (srvStatus == System.ServiceProcess.ServiceControllerStatus.Running)
                    {
                        serviceRunning = true;
                        startRecordingToolStripMenuItem.Enabled = false;
                        stopRecordingToolStripMenuItem.Enabled = true;

                        toolStripButtonPlay.Enabled = false;
                        toolStripButtonStop.Enabled = true;

                        //Started = true;
                        optionsToolStripMenuItem1.Enabled = false;
                        toolStripButtonOptions.Enabled = false;

                        tbTotalChannels.Enabled = true;
                        tbAvailableChannels.Enabled = true;
                        tbOfflineChannels.Enabled = true;
                        tbChannelInUse.Enabled = true;

                        //tbTotalChannels.Text = vr2.ChannelCount.ToString();
                        //tbAvailableChannels.Text = vr2.ChannelCount.ToString();
                        tbOfflineChannels.Text = "0";
                        tbChannelInUse.Text = "";

                        timer1.Enabled = true;
                        timer2.Enabled = true;

                        recordingToolStripMenuItem.Text = "Status: Recording Service Running";
                        toolStripStatusLabel1.Text = "Status: Recording Service Running";

#if SBS_VR
                        runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
                        runningModelToolStripMenuItem.Enabled = false;
#else
                        runningModelToolStripMenuItem.Enabled = false;
#endif
                    }
                    else
                    {
                        startRecordingToolStripMenuItem.Enabled = true;
                        stopRecordingToolStripMenuItem.Enabled = false;

                        toolStripButtonPlay.Enabled = true;
                        toolStripButtonStop.Enabled = false;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());

                    //no service is installed
                    timer1.Enabled = false;

                    startRecordingToolStripMenuItem.Enabled = false;
                    stopRecordingToolStripMenuItem.Enabled = false;

                    toolStripButtonPlay.Enabled = false;
                    toolStripButtonStop.Enabled = false;


                    //Started = false;
                    optionsToolStripMenuItem1.Enabled = true;
                    toolStripButtonOptions.Enabled = true;

                    dataGridView1.Enabled = false;

                    tbTotalChannels.Enabled = false;
                    tbTotalChannels.Text = "";

                    tbAvailableChannels.Enabled = false;
                    tbAvailableChannels.Text = "";

                    tbOfflineChannels.Enabled = false;
                    tbOfflineChannels.Text = "";

                    tbChannelInUse.Enabled = false;
                    tbChannelInUse.Text = "";

                    recordingToolStripMenuItem.Text = "Status: N/A";
                    toolStripStatusLabel1.Text = "Status: N/A";

                    serviceRunning = false;

#if SBS_VR
                    runningModelToolStripMenuItem.Enabled = false;
#elif SmartConnectSystems_VR
                    runningModelToolStripMenuItem.Enabled = false;
#else
                    runningModelToolStripMenuItem.Enabled = true;
#endif
                }

                //start_here1:
                if (serviceRunning)
                {
                    IntPtr resConnect = vr_client.ConnectTo(serverIP, serverPort);

                    if (resConnect == IntPtr.Zero)
                    {
                        LogoutText("Cannot connect to recorder service!");
                        vr_client.Disconnect();
                        timer2.Enabled = false;
                    }
                }
                else
                {
                }

            }
            else if (RunModel == 2)
            {
                /*
                uint resConnect = vr_client.ConnectTo(serverIP, serverPort);

                if (resConnect == 0)
                {
                    LogoutText("Cannot connect to recorder service!");
                    vr_client.Disconnect();
                    timer2.Enabled = false;
                }*/

                StartManageClient();
            }
#endif
        }

        private void openRealtimeListenerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (rtPhone != null)
            {
                rtPhone.Visible = true;
            }
        }
    }


    public class VR2WinAppClient : VR2Client
    {
        public VR2AppMainForm main_form;

        public override void LogoutText(string logInfo)
        {
            base.LogoutText(logInfo);
            //main_form.LogoutText(logInfo);
        }

        public override void ServerConnected(bool bConnected)
        {
            main_form.ServerConnected(bConnected);
        }

        public override void OnCallOffered(int ChanIndex, string CallerIP, string CallerID, string CalleeIP, string CalleeID, uint CallTime, string UniqueID, string AudioFile, int CallDir)
        {
            base.OnCallOffered(ChanIndex, CallerIP, CallerID, CalleeIP, CalleeID, CallTime, UniqueID, AudioFile, CallDir);
            main_form.Recorder_OnCallOffered(ChanIndex, CallerIP, CallerID, CalleeIP, CalleeID, CallTime, UniqueID, AudioFile, CallDir);
        }

        public override void OnCallConnected(int ChanIndex, string CallerIP, string CallerID, string CalleeIP, string CalleeID, uint InitTime, uint ConnectTime, string UniqueID, string AudioFile, int CallDir)
        {
            base.OnCallConnected(ChanIndex, CallerIP, CallerID, CalleeIP, CalleeID, InitTime, ConnectTime, UniqueID, AudioFile, CallDir);
            main_form.Recorder_OnCallConnected(ChanIndex, CallerIP, CallerID, CalleeIP, CalleeID, InitTime, ConnectTime, UniqueID, AudioFile, CallDir);
        }

        public override void OnCallIdle(int ChanIndex, string CallerIP, string CallerID, string CalleeIP, string CalleeID, uint InitTime, uint ConnectTime, uint EndTime, string UniqueID, string AudioFile, int AudioFileNum, int Reason, int CallDir, string DTMFStr)
        {
            base.OnCallIdle(ChanIndex, CallerIP, CallerID, CalleeIP, CalleeID, InitTime, ConnectTime, EndTime, UniqueID, AudioFile, AudioFileNum, Reason, CallDir, DTMFStr);
            main_form.Recorder_OnCallIdle(ChanIndex, CallerIP, CallerID, CalleeIP, CalleeID, InitTime, ConnectTime, EndTime, UniqueID, AudioFile, AudioFileNum, Reason, CallDir, DTMFStr);
        }

        public override void OnCallInfo(int ChanIndex, string CallerIP, string CallerID, string CalleeIP, string CalleeID, string UniqueID, string AudioFile, int CallDir)
        {
            base.OnCallInfo(ChanIndex, CallerIP, CallerID, CalleeIP, CalleeID, UniqueID, AudioFile, CallDir);
            main_form.Recorder_OnCallInfo(ChanIndex, CallerIP, CallerID, CalleeIP, CalleeID, UniqueID, AudioFile, CallDir);
        }

        public override void OnStatusGeneral(string[] members)
        {
            base.OnStatusGeneral(members);
            main_form.Recorder_OnStatusGeneral(members);

        }

        public override void OnStatusChannel(VR2Channel chan)
        {
            base.OnStatusChannel(chan);
            main_form.Recorder_OnStatusChannel(chan);
        }

        public override void OnCallDTMF(int ChanIndex, string KeyPressed, string DTMFStr)
        {
            base.OnCallDTMF(ChanIndex, KeyPressed, DTMFStr);
            main_form.Recorder_OnCallDTMF(ChanIndex, KeyPressed, DTMFStr);
        }

    }
}
