using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace DTMFTest
{
    public partial class Form1 : Form
    {
        public static MyGTAPIEnv env;
        public int tickCnt;

        public int chanNum;
        public bool SIPSrvRunning;
        public int SIPSrvType;
        public string SIPAddr;

        public string DTMFToSend;
        public int[] DTMFChanPos;

        public string[] DTMFChanRcv;

        public Form1()
        {
            InitializeComponent();
            env = null;
            SIPSrvRunning = false;
            SIPSrvType = 0;

            DTMFToSend = "0123456789*#0123456789*#0123456789*#0123456789*#";

            tickCnt = 0;

            chanNum = 0;
        }

        public void On_RecvConnected(int ch)
        {
            if (SIPSrvType == 0) //sender
            {
                DTMFChanPos[ch] = 0;
                env.StartTimer(ch, 1000); //for 1 second later to dialout
            }
            else //DTMF receiver
            {
                DTMFChanRcv[ch] = "";

                if (ch < chanNum / 2)
                {
                    env.Send_EnableDTMF(ch, 0, "", 0);
                    //env.StartTimer(ch, 1000); //for 1 second later to play
                }
                else
                {
                    //env.Send_DuplexConnect(ch, ch - chanNum / 2);
                }
            }
        }

        public void On_RecvIdle(int ch)
        {
            if (SIPSrvType == 0) //sender
            {
                env.StartTimer(ch, 3000); //start another call 3 seconds later
            }
            else if (SIPSrvType == 1) //receiver
            {
                env.Send_DisableDTMF(ch);
                //if(ch < chanNum/2) env.Send_HangUp(ch + chanNum / 2, 0, ""); //disconnect duplex connect channel
            }
        }

        public void On_RecvOffered(int ch, string sCaller, string sCallee, string sDestAddr, string sViaAddr, string sFromIP, ushort nFromPort)
        {
            if (SIPSrvType == 1)
            {
                //receiving side, answer the call
                env.Send_Answer(ch);
            }
        }

        public void On_RecvRinging(int ch)
        {
        }

        public void On_RecvDialing(int ch, string sCaller, string sCallee)
        {
        }

        public void On_Timer(int ch)
        {
            GTAPIASM.GTAPIChan apiChan = env.GetChannel(ch);

            if (SIPSrvType == 0) //outbound
            {
                if (apiChan.ch_status == GTAPIASM.GTAPI_CHANNEL_STATE.IDLE)
                {
                    env.Send_Make(ch, SIPAddr, "");
                }
                else
                {
                    if (DTMFChanPos[ch] >= DTMFToSend.Length)
                    {
                        env.Send_HangUp(ch, 0, "");
                    }
                    else
                    {
                        string s = DTMFToSend[DTMFChanPos[ch]++].ToString();
                        env.Send_PlayDTMFStr(ch, s);
                        env.StartTimer(ch, 1000); //come back one second later
                    }
                }
            }
            else if(SIPSrvType == 1) //inbound
            {
                //env.Send_PlayAudio(ch, Application.StartupPath + "\\somewhere1.wav", 0, "", 0, 0);
            }
        }

        public void On_RecvDTMFKeyDown(int ch, byte keyValue, uint ticks)
        {
            if (SIPSrvType == 1) //inbound
            {
                DTMFChanRcv[ch] += Convert.ToChar(keyValue).ToString();
/*
                if (DTMFChanRcv[ch].Length >= 6 && ch < chanNum/2)
                {
                    //reached 6 digits
                    env.Send_DisableDTMF(ch); //disable DTMF detection
                    env.Send_StopAudio(ch);  //stop playing audio
                    env.Send_DuplexConnect(ch, ch + chanNum);
                    env.Send_Make(ch + chanNum / 2, "<sip:456@192.168.1.201:5060>", "");
                }
 */
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            cbServerType.Items.Add("Sender(Make call and send DTMF)");
            cbServerType.Items.Add("Receiver(Receive call and detect DTMF)");
            cbServerType.SelectedIndex = 0;

            cbChanNum.Items.Add("4");
            cbChanNum.Items.Add("8");
            cbChanNum.Items.Add("16");
            cbChanNum.Items.Add("32");
            cbChanNum.Items.Add("64");
            cbChanNum.Items.Add("128");
            cbChanNum.Items.Add("256");
            cbChanNum.Items.Add("512");
            cbChanNum.SelectedIndex = 0;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (SIPSrvRunning && env != null)
            {
                FreeSIPServer();
            }
        }

        private void cbServerType_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbServerType.SelectedIndex == 0)
            {
                tbSIPAddress.Enabled = true;
            }
            else
            {
                tbSIPAddress.Enabled = false;
            }
        }


        public void InitSIPServer()
        {
            if (env != null) return;

            env = new MyGTAPIEnv();
            env.mainForm = this;

            env.CreateEnv();
            env.SetMainWnd(Handle);

            env.CFG_SetValue("gtsrv.sip.server.model", "1"); //server application

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

            //RTP PORT
            env.CFG_SetValue("gtsrv.sip.rtpstartrange", "32000");
            env.CFG_SetValue("gtsrv.sip.rtpendrange", "36000");

            //Log
            env.CFG_SetValue("gtsrv.log.level", "4");
            env.CFG_SetValue("gtsrv.log.filename", "c:\\dtmftest.txt");

            chanNum = Convert.ToInt32(cbChanNum.Text);

            if (chanNum < 4 || chanNum > 512)
                chanNum = 4;

            //channnel numbers, here we only use 1 channel
            switch (chanNum)
            {
                case 4:
                    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", "4");
                    break;
                case 8:
                    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", "8");
                    break;
                case 16:
                    env.CFG_SetValue("gtsrv.sip.boardnum.per.server", "1");
                    env.CFG_SetValue("gtsrv.sip.spannum.per.board", "2");
                    env.CFG_SetValue("gtsrv.sip.channum.per.span", "8");
                    break;
                case 32:
                    env.CFG_SetValue("gtsrv.sip.boardnum.per.server", "1");
                    env.CFG_SetValue("gtsrv.sip.spannum.per.board", "4");
                    env.CFG_SetValue("gtsrv.sip.channum.per.span", "8");
                    break;
                case 64:
                    env.CFG_SetValue("gtsrv.sip.boardnum.per.server", "1");
                    env.CFG_SetValue("gtsrv.sip.spannum.per.board", "8");
                    env.CFG_SetValue("gtsrv.sip.channum.per.span", "8");
                    break;
                case 128:
                    env.CFG_SetValue("gtsrv.sip.boardnum.per.server", "1");
                    env.CFG_SetValue("gtsrv.sip.spannum.per.board", "8");
                    env.CFG_SetValue("gtsrv.sip.channum.per.span", "16");
                    break;
                case 256:
                    env.CFG_SetValue("gtsrv.sip.boardnum.per.server", "2");
                    env.CFG_SetValue("gtsrv.sip.spannum.per.board", "8");
                    env.CFG_SetValue("gtsrv.sip.channum.per.span", "16");
                    break;
                case 512:
                    env.CFG_SetValue("gtsrv.sip.boardnum.per.server", "4");
                    env.CFG_SetValue("gtsrv.sip.spannum.per.board", "8");
                    env.CFG_SetValue("gtsrv.sip.channum.per.span", "16");
                    break;
            }

            //Internal communication port
            env.CFG_SetValue("gtsrv.net.port", "9924");

            env.CFG_SetValue("gtsrv.sip.prefered.codec", "0,8");

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

            //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

            //env.CFG_SetValue("gtsrv.sip.reg.client.num", "1");
            //env.CFG_SetValue("gtsrv.sip.reg1.displayname", m_sipAccDisplayName);
            //env.CFG_SetValue("gtsrv.sip.reg1.username", m_sipAccUserName);
            //env.CFG_SetValue("gtsrv.sip.reg1.domain", m_sipAccDomainName);
            //env.CFG_SetValue("gtsrv.sip.reg1.proxy", m_sipAccProxyName);
            //env.CFG_SetValue("gtsrv.sip.reg1.authorization", m_sipAccAuthName);
            //env.CFG_SetValue("gtsrv.sip.reg1.password", m_sipAccPassword);
            //env.CFG_SetValue("gtsrv.sip.reg1.expire", "3600");

            //NOT regular key. NOT good to use this key in PROD.
            env.SetAppName("TestServerApp");
            env.CFG_SetValue("gtsrv.licence.key", "M0F7-Y6B5-G8F1-F3XN-J02Y");

            if (!env.StartServer())
            {
                MessageBox.Show("StartServer Failed! Please make sure the SIP port is not being used by another application!");
            }

            btnStart.Enabled = false;
            btnStop.Enabled = true;

            SIPSrvRunning = true;
            SIPSrvType = cbServerType.SelectedIndex;

            if (SIPSrvType == 0)
            {
                //outbound
                DTMFChanPos = new int[chanNum];

                for (int i = 0; i < chanNum; i++)
                {
                    env.StartTimer(i, 4000); //start the call 4 seconds later.
                    DTMFChanPos[i] = 0;
                }

                SIPAddr = "<sip:" + tbSIPAddress.Text + ">";
            }
            else
            {
                DTMFChanRcv = new string[chanNum];
                for (int i = 0; i < chanNum; i++)
                {
                    DTMFChanRcv[i] = "";
                }
            }

            dataGridView1.Enabled = true;
            dataGridView1.RowCount = chanNum;
            dataGridView1.ColumnCount = 2;
            dataGridView1.Columns[0].Name = "Status";
            if (SIPSrvType == 0)
                dataGridView1.Columns[1].Name = "DTMF Sent";
            else
                dataGridView1.Columns[1].Name = "DTMF Received";

            for (int i = 0; i < chanNum; i++)
            {
                dataGridView1.Rows[i].HeaderCell.Value = i.ToString();
            }

            timer1.Enabled = true;

            tickCnt = 0;
        }

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

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

            btnStart.Enabled = true;
            btnStop.Enabled = false;

            SIPSrvRunning = false;
            SIPSrvType = 0;

            dataGridView1.Enabled = false;
        }

        public void UpdateGrids()
        {
            for (int i = 0; i < chanNum; i++)
            {
                GTAPIASM.GTAPIChan chan = env.GetChannel(i);
                if (chan != null)
                {
                    switch (chan.ch_status)
                    {
                        case GTAPIASM.GTAPI_CHANNEL_STATE.CONNECTED:
                            dataGridView1.Rows[i].Cells[0].Value = "CONNECTED";
                            break;
                        case GTAPIASM.GTAPI_CHANNEL_STATE.DIALING:
                            dataGridView1.Rows[i].Cells[0].Value = "DIALING";
                            break;
                        case GTAPIASM.GTAPI_CHANNEL_STATE.IDLE:
                            dataGridView1.Rows[i].Cells[0].Value = "IDLE";
                            break;
                    }
                }

                if(SIPSrvType == 0)
                    dataGridView1.Rows[i].Cells[1].Value = DTMFToSend.Substring(0, DTMFChanPos[i]);
                else
                    dataGridView1.Rows[i].Cells[1].Value = DTMFChanRcv[i];

            }

            dataGridView1.Update();
        }

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

                tickCnt++;

                if (tickCnt % 10 == 0)
                {
                    tickCnt = 0;

                    UpdateGrids();
                }
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            InitSIPServer();
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            FreeSIPServer();
        }



    }
}