using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.IO;

namespace CFBandwidth
{
    public partial class Form1 : Form
    {

        private delegate int listDelegate(string text);
        listDelegate listbox2delegate;
        listDelegate listbox1delegate;
        listDelegate labeldelegate;
        BandwidthMeter bm;
        Linear_Regression ln;

        public Form1()
        {
            InitializeComponent();
            listbox2delegate = new listDelegate(listBox2.Items.Add);
            listbox1delegate = new listDelegate(listBox1.Items.Add);
            labeldelegate = new listDelegate(label1SetText);
        }

        public void updateListBox1(string s)
        {
            this.Invoke(listbox1delegate, new object[] { s });
            try
            {
                this.Refresh();
                listBox1.TopIndex = listBox1.Items.Count - 3;
            }
            catch (Exception e)
            {
            }
        }

        public void updateListBox2(string s)
        {
            
            this.Invoke(listbox2delegate, new object[] { s });
            try
            {
                this.Refresh();
                listBox2.TopIndex = listBox2.Items.Count - 3;
            }
            catch (Exception e)
            {
            }
        }

        public int label1SetText(string _text)
        {
            label6.Text = _text.ToString();
            return 0;
        }

        public void updateLabel(string s)
        {
            this.Invoke(labeldelegate, new object[] { s });
            try
            {
                this.Refresh();
                label6.Text = s.ToString();
            }
            catch (Exception e)
            {
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            bool error = false;

            int mtu=0;
            int min=0;
            int step=0;
            int iterrations=0;
            int timeout=0;
            IPAddress destination = null;


            try
            {
                destination = IPAddress.Parse(textBoxDestination.Text);
            }
            catch (Exception exception)
            {
                MessageBox.Show("Not a valid IP address, correct format \"192.168.1.1\"", "Error");
                error = true;
            }

            try
            {
                mtu = Int16.Parse(textBoxMTU.Text);
            }
            catch
            {
                error = true;
                MessageBox.Show("Wrong MTU size", "Error");
            }

            try
            {
                min = Int16.Parse(textBoxMIN.Text);
            }
            catch
            {
                error = true;
                MessageBox.Show("Wrong Min size", "Error");
            }

            try
            {
                step = Int16.Parse(textBoxStep.Text);
            }
            catch
            {
                error = true;
                MessageBox.Show("Wrong step value", "Error");
            }

            try
            {
                iterrations = Int16.Parse(textBoxIterations.Text);
            }
            catch
            {
                error = true;
                MessageBox.Show("Wrong iterrations number", "Error");
            }

            try
            {
                timeout = Int16.Parse(textBoxTimeOut.Text);
            }
            catch
            {
                error = true;
                MessageBox.Show("Wrong timeout value", "Error");
            }


            if (error == false)
            {

                foreach (Control c in this.Controls)
                {
                    c.Visible = false;
                }
                this.listBox1.Visible = true;
                this.listBox2.Visible = true;
                this.label6.Visible = true;
                
                this.Refresh();
                
                bm = new BandwidthMeter(this,mtu,min,step,iterrations,timeout,destination);
                this.updateListBox1("Bandwidth measurements started ...");
                //bm.measurements2();
                
                bm.measurments1();
                ln = new Linear_Regression(bm.results, bm.sizes);
                this.updateListBox1("Bandwidth measurements completed");
                this.updateListBox1("---------------------------------------------------------");
                this.updateListBox1("The Measured Bandwidht is " + (2*Math.Round(ln.getBandwidth(),2)).ToString());
                button3.Visible = true;
                button2.Visible = true;

            }




        }

        private void label2_ParentChanged(object sender, EventArgs e)
        {

        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Graph graph = new Graph(bm,ln);
            graph.Visible = true;
            graph.Activate();
            graph.Refresh();
        }

        private void menuItem1_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            string logFile = bm.getExecutionTime().ToString().Replace(@"/", @"_").Replace(@"\", @"_").Replace(":", "-").Replace(" ", "_") + ".txt";
            
            System.IO.TextWriter tw = new StreamWriter("Bandwidth" + logFile);
           
            tw.WriteLine("Bandwidth Log File");
            tw.WriteLine(" ");
            tw.WriteLine("Execution Time: " + bm.getExecutionTime());
            tw.WriteLine("Measured Bandwidth: " + (2*Math.Round(ln.getBandwidth(), 2)).ToString() + " Mb/s");
            tw.WriteLine(" ");
            tw.WriteLine("Destination Ip Address: " + bm.destination.ToString());
            tw.WriteLine("MTU: " + bm.MTU.ToString()+ " bytes");
            tw.WriteLine("Start packet size: " + bm.MIN.ToString() + " bytes");
            tw.WriteLine("Step size: " + bm.step.ToString() + " bytes");
            tw.WriteLine("Iteration: " + bm.iteratons.ToString());
            tw.WriteLine("Timeout: " + bm.timeout.ToString() + " ms");
            tw.WriteLine("Regression Line: y =" + Math.Round(ln.getA(), 2).ToString() + "*x + " + Math.Round(ln.getB(), 2).ToString());
    
            int i = 0;
            int s = bm.MIN;
            tw.WriteLine(" ");
            foreach (List<double> list in bm.ListRtt)
            {
                
                foreach (double rtt in list)
                {
                    tw.WriteLine(" "+i.ToString() + " size: " + s.ToString()+ ", RTT: " + (rtt/1000).ToString() + " ms");
                    i++;
                }
                tw.WriteLine(" ");
                s = s + bm.step;
                i = 0;
            }
             
            
            tw.Close();

            this.updateListBox1("Log Created");
        }

        private void textBoxDestination_TextChanged(object sender, EventArgs e)
        {

        }
    }
}