using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.IO;
using Microsoft.Win32;
using System.Threading;

namespace VR2WinApp
{
    public partial class RTListenSoftphone : Form
    {
        public XmlDocument xmlCfg;
        public const string VR2_REG_KEY_ROOT = "SOFTWARE\\PC Best Networks Inc\\VoIP Recorder V2\\";

        public bool doClose;

        //real time listening feature
        public MyGTAPIEnv env;

        public string RTSrvIP;
        public ushort RTSrvPort;

        public ushort RTSoftSIPPort;
        public ushort RTSoftRTPPort;
        public int MaxChanNum;

        public RTListenSoftphone()
        {
            InitializeComponent();
            doClose = false;

            RTSrvIP = "127.0.0.1";
            RTSrvPort = 5060;

            RTSoftSIPPort = 7832;
            RTSoftRTPPort = 18810;

            MaxChanNum = 0;
        }

        private void RTListenSoftphone_Load(object sender, EventArgs e)
        {

            RegistryKey keyPCBest;
            try
            {
                keyPCBest = Registry.CurrentUser.OpenSubKey(VR2_REG_KEY_ROOT);
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.ToString());
                keyPCBest = null;
            }

            if (keyPCBest != null)
            {
                try
                {
                    // Create data for the TestSettings subkey.

                    if(keyPCBest.GetValue("RTSrvIP") != null)
                    {
                        try
                        {
                            RTSrvIP = (string)keyPCBest.GetValue("RTSrvIP");
                        }
                        catch (Exception)
                        {
                            RTSrvIP = "127.0.0.1";
                        }
                    }

                    if (RTSrvIP == "") RTSrvIP = "127.0.0.1";

                    try
                    {
                        RTSrvPort = Convert.ToUInt16((string)keyPCBest.GetValue("RTSrvPort"));
                    }
                    catch (Exception)
                    {
                        RTSrvPort = 5060;
                    }

                    if (RTSrvPort == 0) RTSrvPort = 5060;

                    try
                    {
                        RTSoftSIPPort = Convert.ToUInt16((string)keyPCBest.GetValue("RTSoftSIPPort"));
                    }
                    catch (Exception)
                    {
                        RTSoftSIPPort = 7832;
                    }

                    if (RTSoftSIPPort == 0) RTSoftSIPPort = 7832;

                    try
                    {
                        RTSoftRTPPort = Convert.ToUInt16((string)keyPCBest.GetValue("RTSoftRTPPort"));
                    }
                    catch (Exception)
                    {
                        RTSoftRTPPort = 18810;
                    }

                    if (RTSoftRTPPort == 0) RTSoftRTPPort = 18810;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }

            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";
            }

            InitSIPServer();
        }

        private void RTListenSoftphone_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (doClose)
            {
                FreeSIPServer();
            }
            else
            {
                this.Visible = false;
                e.Cancel = true;
            }
        }

        //////////////////////////////////////////////////////////////////////
        //Softphone Methods and Events
        //////////////////////////////////////////////////////////////////////
        public bool InitSIPServer()
        {
            int rtpend;

            env = new MyGTAPIEnv();
            env.mainForm = this;
            env.CreateEnv();
            env.SetMainWnd(Handle);

            env.CFG_SetValue("gtsrv.sip.server.model", "0");

            //SIP IP Address you want to use on local
            //Leave it unset if you want to listen on all the network interface
            //CFG_SetValue("gtsrv.sip.ip.address", "");

            //SIP Port, default 5060
            env.CFG_SetValue("gtsrv.sip.ip.port", RTSoftSIPPort.ToString());

            //RTP PORT
            env.CFG_SetValue("gtsrv.sip.rtpstartrange", RTSoftRTPPort.ToString());
            rtpend = RTSoftRTPPort + 20;
            env.CFG_SetValue("gtsrv.sip.rtpendrange", rtpend.ToString());

            //Log
            env.CFG_SetValue("gtsrv.log.level", "4");
            env.CFG_SetValue("gtsrv.log.filename", Application.StartupPath + "\\RTSoftphone.txt");

            //Prefered codec list
            env.CFG_SetValue("gtsrv.sip.prefered.codec", "0,8,3");
            //env.CFG_SetValue("gtsrv.sip.prefered.video.codec", "34,115,124")

            //NAT or STUN
            /*
            if (cfgWrap.StunServer.Length > 0)
            {
                env.CFG_SetValue("gtsrv.sip.stun.server", cfgWrap.StunServer);
            }
            else
            {
                env.CFG_SetValue("gtsrv.sip.use.nat.addr", cfgWrap.UseNATAddr ? "1" : "0");
            }*/

            //JB buffer and dirctX buffer settings, DO NOT change
            //env.CFG_SetValue("gtsrv.sip.jb.min.delay", "0")
            //env.CFG_SetValue("gtsrv.sip.jb.max.delay", "5")
            //env.CFG_SetValue("gtsrv.sip.jb.adaptive", "0")
            //env.CFG_SetValue("gtsrv.sip.jb.get.all.data", "1")
            //env.CFG_SetValue("gtsrv.sip.dx.playback.delay", "2")

            //channnel numbers, here we only use 1 channel
            env.CFG_SetValue("gtsrv.sip.boardnum.per.server", "1");
            env.CFG_SetValue("gtsrv.sip.spannum.per.board", "1");
            env.CFG_SetValue("gtsrv.sip.channum.per.span", "1");

            //define inbound and outbound channels, NOT USEFUL ANYMORE. DO NOT USE
            //env.CFG_SetValue("gtsrv.channel.inbound", "0-3");
            //env.CFG_SetValue("gtsrv.channel.outbound", "4-15");

            //Internal communication port
            env.CFG_SetValue("gtsrv.net.port", "9427"); //any port you like

            //conference room
            //env.CFG_SetValue("gtsrv.sip.conference.room", "1")

            //Configuration file, if you want to define parameters in a file
            //env.CFG_SetValue(GTSRV_CFG_FILENAME, "GTSimpelPhone.ini");

            //Application name, it is related to sdk licence
            //Please contact PCBest Network(www.pcbest.net) to get licence info
            env.SetAppName("VR2RTSoftphone");

            XmlElement root = xmlCfg.DocumentElement;
            XmlNode tmpNode = root.SelectSingleNode("//VoiceRecorder/LicKey");
            if (tmpNode != null)
            {
                env.CFG_SetValue("gtsrv.licence.key", tmpNode.InnerText.Trim());
                env.CFG_SetValue("gtsrv.lic.file.dir", Application.StartupPath);
            }


            //env.CFG_SetValue("gtsrv.sip.conference.room", "1")

            //define outbound route, leave them unset if you don't know
            //env.CFG_SetValue("gtsrv.sip.outbound.via.type", "0");
            //env.CFG_SetValue("gtsrv.sip.outbound.via.proxy", "");

            //set sip client user info ***** If you want to take incoming calls, you must set this value,
            // or you can only answer calls by your IP address
            //you must get an account from sip service provider first

            if (env.StartServer())
            {
                //env.Send_GetRegStatus(0);
                lbRTChanStatus.Text = "Idle";
                btnListen.Text = "Listen";

                timer1.Enabled = true;

                return true;
            }
            else
            {
                MessageBox.Show("Realtime Softphone Start Failed! Please make sure the SIP port(6872) is not being used by another application!");
                lbRTChanStatus.Text = "ERROR: START PHONE";
                btnListen.Enabled = false;

                return false;
            }
        }

        public bool FreeSIPServer()
        {
            timer1.Enabled = false;

            if (env != null)
            {
                env.StopServer();
                env.DestroyEnv();
                env = null;
            }
            return true;
        }

        public void On_RecvConnected(int ch)
        {
            env.StopSound(); //stop the ring tone or ringback tone

            //Send_SetChanInConference(0, -1, 1)
            //Send_SetChanInConference(0, ch, 1)
            env.Send_StartDXAudio(ch); //because this is a client phone, we start DirectX audio

            btnListen.Text = "Stop";
            lbRTChanStatus.Text = "Connected";

            cbChanID.Enabled = false;
            btnOptions.Enabled = false;
        }

        public void On_RecvOffered(int ch, string sCaller, string sCallee, string sDestAddr, string sViaAddr, string sFromIP, ushort nFromPort)
        {
            //reject incoming call
            env.Send_HangUp(ch, 0, "");
        }

        public void On_RecvDialing(int ch, string sCaller, string sCallee)
        {
            btnListen.Text = "Stop";
            lbRTChanStatus.Text = "Dialing";
        }

        public void On_RecvRinging(int ch)
        {
            btnListen.Text = "Stop";
            lbRTChanStatus.Text = "Ringing";

            env.StopSound();
            env.PlayRemoteRingSound();
        }

        public void On_RecvIdle(int ch, int code, string desc)
        {
            btnListen.Text = "Listen";
            lbRTChanStatus.Text = "Idle";

            cbChanID.Enabled = true;
            btnOptions.Enabled = true;

            env.StopSound();

            //Send_SetChanInConference(0, -1, 0)
            //Send_SetChanInConference(0, ch, 0)
        }

        public void On_RecvRegStatus(int user_id, int status, int regtime)
        {
        }

        public void On_RecvHolding(int ch, int hold_on)
        {
            GTAPIASM.GTAPIChan chan;

            chan = env.GetChannel(ch);

            if (chan.ch_status == GTAPIASM.GTAPI_CHANNEL_STATE.CONNECTED)
            {
            }

            if (chan.ch_status == GTAPIASM.GTAPI_CHANNEL_STATE.HOLDING)
            {
            }

            if (chan.ch_status == GTAPIASM.GTAPI_CHANNEL_STATE.BE_HOLDED)
            {
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (env != null)
            {
                env.ProcessGTAPIEvent();
            }
        }

        private void btnListen_Click(object sender, EventArgs e)
        {
            int ch = Convert.ToInt32(cbChanID.Text);
            if (ch >= 1 && ch <= MaxChanNum)
            {
                if (btnListen.Text == "Stop")
                {
                    env.Send_HangUp(0, 0, "");
                }
                else
                    MakeCallOut(ch);
            }
        }

        public void MakeCallOut(int ch)
        {
            string calledNum;
            calledNum = "<sip:" + ch.ToString() + "@" + RTSrvIP + ":" + RTSrvPort.ToString() + ">";
            env.Send_Make(0, calledNum, "");
        }

        private void btnOptions_Click(object sender, EventArgs e)
        {
            bool softPhoneSettingChanged = false;

            RTListenerOptions rt = new RTListenerOptions();
            rt.RTSrvIP = RTSrvIP;
            rt.RTSrvPort = RTSrvPort;
            rt.RTSoftSIPPort = RTSoftSIPPort;
            rt.RTSoftRTPPort = RTSoftRTPPort;

            if (rt.ShowDialog() == DialogResult.OK)
            {
                RTSrvIP = rt.RTSrvIP;
                RTSrvPort = rt.RTSrvPort;


                if (RTSoftSIPPort != rt.RTSoftSIPPort || RTSoftRTPPort != rt.RTSoftRTPPort)
                    softPhoneSettingChanged = true;

                RTSoftSIPPort = rt.RTSoftSIPPort;
                RTSoftRTPPort = rt.RTSoftRTPPort;

                RegistryKey keyPCBest;
                try
                {
                    keyPCBest = Registry.CurrentUser.CreateSubKey(VR2_REG_KEY_ROOT);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                    return;
                }

                if (keyPCBest == null)
                    return;

                try
                {
                    // Create data for the TestSettings subkey.
                    keyPCBest.SetValue("RTSrvIP", RTSrvIP);
                    keyPCBest.SetValue("RTSrvPort", RTSrvPort.ToString());

                    keyPCBest.SetValue("RTSoftSIPPort", RTSoftSIPPort.ToString());
                    keyPCBest.SetValue("RTSoftRTPPort", RTSoftRTPPort.ToString());
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                    return;
                }

                if (softPhoneSettingChanged)
                {
                    FreeSIPServer();
                    Thread.Sleep(2000);
                    InitSIPServer();
                }

            }
        }
    }
}
