// clsCnn
// Copyright (C) 2008 Karel Jordaan karel_jordaan@yahoo.com.au
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

using System;
using System.Diagnostics;
using System.Windows.Forms;
using FileScope;
using FileScope.Gnutella2;
using GUIControlLogic.Error;

namespace ZANZIClient
{
    /// <summary>
    /// Summary description for clsDiscovery.
    /// </summary>
    public class clsCnn
    {
        //zzoi 3june2008
        //in order to prevent cross thread errors

        #region Delegates

        public delegate void UpdateUICallBack(int sckNr);

        public delegate void UpdateUICallBackG2New(string addr, int sckNr);

        public delegate void UpdateUICallBackG2Update(int sckNr, string bwInOut);

        #endregion

        private ctrlCnn m_ctrl;


        public clsCnn()
        {
            //
            // TODO: Add constructor logic here
            //

            try
            {
                //register for events
                GUIBridge.G2JustConnectedEvent += G2JustConnected;
                GUIBridge.G2JustDisconnectedeEvent += G2JustDisconnected;
                GUIBridge.G2NewConnectionEvent += G2NewConnection;
                GUIBridge.G2UpdateEvent += G2Update;
            }
            catch (Exception  ex)
            {
                new clsExeption(ex);
                //ErrByte = 1;
            }
        }

        public ctrlCnn GetCnnCtrl()
        {
            try
            {
                ctrlCnn ctrl = new ctrlCnn(this);
                m_ctrl = ctrl;
                //LoadCnn(ctrl);
                return ctrl;
            }
            catch (Exception  ex)
            {
                new clsExeption(ex);
                //ErrByte = 1;
                return null;
            }
        }


        public void G2NewConnection(string addr, int sockNum)
        {
            try
            {
                //zzoi 3june2008 this invoke solves the cross thread error
                //this.Invoke(new UpdateUICallBack(G2JustDisconnected_lstUpdate), (sockNum));


                if (m_ctrl.lstCnn.InvokeRequired)
                {
                    m_ctrl.lstCnn.Invoke(new UpdateUICallBackG2New(G2NewConnection_lstUpdate), (addr), (sockNum));
                }
                else
                {
                    G2NewConnection_lstUpdate(addr, sockNum);
                }

                //zzoi 3june2008 make sure that the item is not already in the list
                //ListViewItem lvii;
                //for (int x = 0; x < m_ctrl.lstCnn.Items.Count; x++)
                //{
                //    lvii = (ListViewItem)m_ctrl.lstCnn.Items[x];
                //    //if(lvi.SubItems[0].Text == FileScope.Gnutella2.Sck.scks[sockNum].address)
                //    if ((int)lvii.Tag == sockNum)
                //    {
                //        return;
                //    }
                //}

                //string[] str = addr.Split(':');
                //string[] subitems = new string[6];
                //subitems[0] = str[0]; //address IP number
                //subitems[1] = "Connecting"; //status 
                //subitems[2] = str[1]; // "0"; //port
                //subitems[3] = "0.00 / 0.00"; //bandwith 
                //subitems[3] = "?"; //mode hub or leave
                //subitems[4] = "?"; //leaves
                //subitems[5] = "?"; //url
                ////subitems[6] = "?"; //name


                //ListViewItem lvi = new ListViewItem(subitems);
                //lvi.Tag = sockNum;
                //m_ctrl.lstCnn.Items.Add(lvi);
                //m_ctrl.Invalidate();
                //Application.DoEvents();
            }
            catch (Exception  ex)
            {
                new clsExeption(ex);
                //ErrByte = 1;
            }
        }


        public void G2NewConnection_lstUpdate(string addr, int sockNum)
        {
            try
            {
                //zzoi 3june2008 make sure that the item is not already in the list
                ListViewItem lvii;
                for (int x = 0; x < m_ctrl.lstCnn.Items.Count; x++)
                {
                    lvii = m_ctrl.lstCnn.Items[x];
                    //if(lvi.SubItems[0].Text == FileScope.Gnutella2.Sck.scks[sockNum].address)
                    if ((int) lvii.Tag == sockNum)
                    {
                        return;
                    }
                }

                string[] str = addr.Split(':');
                string[] subitems = new string[6];
                subitems[0] = str[0]; //address IP number
                subitems[1] = "Connecting"; //status 
                //subitems[2] = str[1]; // "0"; //port
                subitems[2] = Sck.scks[sockNum].port.ToString();
                subitems[3] = "0.00 / 0.00"; //bandwith 
                subitems[3] = "?"; //mode hub or leave
                subitems[4] = "?"; //leaves
                subitems[5] = "?"; //url
                //subitems[6] = "?"; //name


                ListViewItem lvi = new ListViewItem(subitems);
                lvi.Tag = sockNum;
                m_ctrl.lstCnn.Items.Add(lvi);
                m_ctrl.Invalidate();
                Application.DoEvents();
            }
            catch (Exception ex)
            {
                new clsExeption(ex);
                //ErrByte = 1;
            }
        }

        public void G2JustConnected(int sockNum)
        {
            try
            {
                //zzoi 3june2008 this invoke solves the cross thread error
                //this.Invoke(new UpdateUICallBack(G2JustDisconnected_lstUpdate), (sockNum));


                if (m_ctrl.lstCnn.InvokeRequired)
                {
                    m_ctrl.lstCnn.Invoke(new UpdateUICallBack(G2JustConnected_lstUpdate), (sockNum));
                }
                else
                {
                    G2JustConnected_lstUpdate(sockNum);
                }


                //foreach (ListViewItem lvi in 	m_ctrl.lstCnn.Items)
                //    //if(lvi.SubItems[8].Text == sockNum.ToString())
                //    if ((int) lvi.Tag == sockNum)
                //    {
                //        if (Sck.scks[sockNum].incoming)
                //            lvi.SubItems[0].Text = Sck.scks[sockNum].RemoteIP();
                //        lvi.SubItems[1].Text = "Connected";
                //        lvi.SubItems[5].Text = Sck.scks[sockNum].mode.ToString();
                //        lvi.SubItems[7].Text = Sck.scks[sockNum].vendor;
                //        lvi.SubItems[8].Text = sockNum.ToString();
                //        //						if(FileScope.Gnutella2.Sck.scks[sockNum].mode == Gnutella2.G2Mode.Ultrapeer)
                //        //							//lvi.ForeColor = FileScope.Stats.settings.clHighlight1;
                //        //						else
                //        //							//lvi.ForeColor = FileScope.Stats.settings.clHighlight2;
                //        //						return;
                //        m_ctrl.Invalidate();
                //        Application.DoEvents();
                //    }

                //Debug.WriteLine("Connection G2JustConnected shouldn't have gotten this far");
            }
            catch (Exception  ex)
            {
                new clsExeption(ex);
                //ErrByte = 1;
            }
            //{
            //    Debug.WriteLine("Error Connection G2JustConnected");
            //}
        }


        public void G2JustConnected_lstUpdate(int sockNum)
        {
            try
            {
                foreach (ListViewItem lvi in m_ctrl.lstCnn.Items)
                    //if(lvi.SubItems[8].Text == sockNum.ToString())
                    if ((int) lvi.Tag == sockNum)
                    {
                        if (Sck.scks[sockNum].incoming)
                            lvi.SubItems[0].Text = Sck.scks[sockNum].RemoteIP();
                        lvi.SubItems[1].Text = "Connected";
                        lvi.SubItems[5].Text = Sck.scks[sockNum].mode.ToString();
                        //lvi.SubItems[7].Text = Sck.scks[sockNum].vendor;
                        //lvi.SubItems[8].Text = sockNum.ToString();
                        //						if(FileScope.Gnutella2.Sck.scks[sockNum].mode == Gnutella2.G2Mode.Ultrapeer)
                        //							//lvi.ForeColor = FileScope.Stats.settings.clHighlight1;
                        //						else
                        //							//lvi.ForeColor = FileScope.Stats.settings.clHighlight2;
                        //						return;
                        m_ctrl.Invalidate();
                        Application.DoEvents();
                    }

                //Debug.WriteLine("Connection G2JustConnected shouldn't have gotten this far");
            }
            catch (Exception ex)
            {
                new clsExeption(ex);
                //ErrByte = 1;
            }
            //{
            //    Debug.WriteLine("Error Connection G2JustConnected");
            //}
        }

        public void G2Update(int sockNum, string bwInOut)
        {
            try
            {
                //zzoi 3june2008 this invoke solves the cross thread error
                //this.Invoke(new UpdateUICallBack(G2JustDisconnected_lstUpdate), (sockNum));


                if (m_ctrl.lstCnn.InvokeRequired)
                {
                    m_ctrl.lstCnn.Invoke(new UpdateUICallBackG2Update(G2Update_lstUpdate), (sockNum), (bwInOut));
                }
                else
                {
                    G2Update_lstUpdate(sockNum, bwInOut);
                }


                //zzoi 3june2008 this creates a cross thread error

                //    //				if(	m_ctrl.lstCnn.SelectedIndex != 1)
                //    //					return;
                //    foreach (ListViewItem lvi in 	m_ctrl.lstCnn.Items)
                //        //if(lvi.SubItems[8].Text == FileScope.Gnutella2.Sck.scks[sockNum].address)
                //        if ((int) lvi.Tag == sockNum)
                //        {
                //            if (lvi.SubItems[1].Text == "Connecting")
                //                lvi.SubItems[1].Text = "Handshaking";
                //            if (lvi.SubItems[3].Text != bwInOut)
                //                lvi.SubItems[3].Text = bwInOut;
                //            string leavesData = Sck.scks[sockNum].leaves.ToString() + @" / " +
                //                                Sck.scks[sockNum].maxleaves.ToString();
                //            if (lvi.SubItems[4].Text != leavesData)
                //                lvi.SubItems[4].Text = leavesData;


                //            m_ctrl.Invalidate();
                //            Application.DoEvents();


                //            return;
                //        }
            }
            catch (Exception ex)
            {
                new clsExeption(ex);
                //ErrByte = 1;
            }
        }

        public void G2Update_lstUpdate(int sockNum, string bwInOut)
        {
            try
            {
                bool itmupdated = false;
                //				if(	m_ctrl.lstCnn.SelectedIndex != 1)
                //					return;
                foreach (ListViewItem lvi in m_ctrl.lstCnn.Items)
                    //if(lvi.SubItems[8].Text == FileScope.Gnutella2.Sck.scks[sockNum].address)
                    if ((int) lvi.Tag == sockNum)
                    {
                        //itm in list
                        itmupdated = true;

                        if (lvi.SubItems[1].Text == "Connecting")
                            lvi.SubItems[1].Text = "Handshaking";
                        if (lvi.SubItems[3].Text != bwInOut)
                            lvi.SubItems[3].Text = bwInOut;
                        string leavesData = Sck.scks[sockNum].leaves + @" / " +
                                            Sck.scks[sockNum].maxleaves;
                        if (lvi.SubItems[4].Text != leavesData)
                            lvi.SubItems[4].Text = leavesData;


                        m_ctrl.Invalidate();
                        Application.DoEvents();


                        return;
                    }

                //when the ctrl was not loaded when the connection was made the item will not be in the list to
                //update
                //create the item by calling G2JustConnected_lstUpdate

                if (!itmupdated)
                {
                    G2NewConnection_lstUpdate(Sck.scks[sockNum].address, sockNum);
                    G2JustConnected_lstUpdate(sockNum);
                    //and recall self to update
                    G2Update_lstUpdate(sockNum, bwInOut);
                }
            }
            catch (Exception ex)
            {
                new clsExeption(ex);
                //ErrByte = 1;
            }
        }


        public void G2JustDisconnected(int sockNum)
        {
            try
            {
                //zzoi 3june2008 this invoke solves the cross thread error
                //this.Invoke(new UpdateUICallBack(G2JustDisconnected_lstUpdate), (sockNum));


                if (m_ctrl.lstCnn.InvokeRequired)
                {
                    m_ctrl.lstCnn.Invoke(new UpdateUICallBack(G2JustDisconnected_lstUpdate), (sockNum));
                }
                else
                {
                    G2JustDisconnected_lstUpdate(sockNum);
                }


                //zzoi 3june2008 this creates a cross thread error
                //ListViewItem lvi;
                //for (int x = 0; x < m_ctrl.lstCnn.Items.Count; x++)
                //{
                //    lvi = (ListViewItem) m_ctrl.lstCnn.Items[x];
                //    //if(lvi.SubItems[0].Text == FileScope.Gnutella2.Sck.scks[sockNum].address)
                //    if ((int) lvi.Tag == sockNum)

                //    {
                //        m_ctrl.lstCnn.Items.RemoveAt(x);

                //        m_ctrl.Invalidate();
                //        Application.DoEvents();

                //        return;
                //    }
                //}
            }
            catch (Exception  ex)
            {
                new clsExeption(ex);
                //ErrByte = 1;
            }
        }

        //update the lst in this thread
        public void G2JustDisconnected_lstUpdate(int sockNum)
        {
            try
            {
                ListViewItem lvi;


                for (int x = 0; x < m_ctrl.lstCnn.Items.Count; x++)
                {
                    lvi = m_ctrl.lstCnn.Items[x];
                    //if(lvi.SubItems[0].Text == FileScope.Gnutella2.Sck.scks[sockNum].address)
                    if ((int) lvi.Tag == sockNum)
                    {
                        m_ctrl.lstCnn.Items.RemoveAt(x);

                        m_ctrl.Invalidate();
                        Application.DoEvents();

                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                new clsExeption(ex);
                //ErrByte = 1;
            }
        }


        public void Disconnect()
        {
        }
    }
}