using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Text.RegularExpressions;
using System.Collections;
using System.Globalization;
using System.Threading;

namespace ArdupilotMega.GCSViews
{
    public partial class Configuration : MyUserControl
    {
        Hashtable param = new Hashtable();
        Hashtable changes = new Hashtable();
        static Hashtable tooltips = new Hashtable();
        internal bool startup = true;
        List<CultureInfo> languages = new List<CultureInfo>();

        public struct paramsettings // hk's
        {
            public string name;
            public float minvalue;
            public float maxvalue;
            public float normalvalue;
            public float scale;
            public string desc;
        }

        public Configuration()
        {
            InitializeComponent();

            // fix for dup name
            XTRK_ANGLE_CD1.Name = "XTRK_ANGLE_CD";
        }

        private void Configuration_Load(object sender, EventArgs e)
        {
            // read tooltips
            if (tooltips.Count == 0)
                readToolTips();

            // prefill all fields
            param = MainV2.comPort.param;
            processToScreen();


            // enable disable relevbant hardware tabs
            if (MainV2.APMFirmware == MainV2.Firmwares.ArduPilotMega)
            {
                ConfigTabs.SelectedIndex = 0;
                TabAPM2.Enabled = true;
                TabAC2.Enabled = false;
            }
            else
            {
                ConfigTabs.SelectedIndex = 1;
                TabAPM2.Enabled = false;
                TabAC2.Enabled = true;
            }

            // setup up camera button states
            if (MainV2.cam != null)
            {
                BUT_videostart.Enabled = false;
                CHK_hudshow.Checked = GCSViews.FlightData.myhud.hudon;
            }
            else
            {
                BUT_videostart.Enabled = true;
            }

            // setup speech states
            if (MainV2.config["speechenable"] != null)
                CHK_enablespeech.Checked = bool.Parse(MainV2.config["speechenable"].ToString());
            if (MainV2.config["speechwaypointenabled"] != null)
                CHK_speechwaypoint.Checked = bool.Parse(MainV2.config["speechwaypointenabled"].ToString());
            if (MainV2.config["speechmodeenabled"] != null)
                CHK_speechmode.Checked = bool.Parse(MainV2.config["speechmodeenabled"].ToString());
            if (MainV2.config["speechcustomenabled"] != null)
                CHK_speechcustom.Checked = bool.Parse(MainV2.config["speechcustomenabled"].ToString());
            if (MainV2.config["speechbatteryenabled"] != null)
                CHK_speechbattery.Checked = bool.Parse(MainV2.config["speechbatteryenabled"].ToString());
            if (MainV2.config["speechaltenabled"] != null)
                CHK_speechaltwarning.Checked = bool.Parse(MainV2.config["speechaltenabled"].ToString());

            // this can't fail because it set at startup
            NUM_tracklength.Value = int.Parse(MainV2.config["NUM_tracklength"].ToString());

            // get wps on connect
            if (MainV2.config["loadwpsonconnect"] != null)
                CHK_loadwponconnect.Checked = bool.Parse(MainV2.config["loadwpsonconnect"].ToString());

            // setup other config state
            if (MainV2.config["CHK_resetapmonconnect"] != null)
                CHK_resetapmonconnect.Checked = bool.Parse(MainV2.config["CHK_resetapmonconnect"].ToString());

            CMB_rateattitude.Text = MainV2.cs.rateattitude.ToString();
            CMB_rateposition.Text = MainV2.cs.rateposition.ToString();
            CMB_raterc.Text = MainV2.cs.raterc.ToString();
            CMB_ratestatus.Text = MainV2.cs.ratestatus.ToString();


            //set hud color state
            string hudcolor = (string)MainV2.config["hudcolor"];

            CMB_osdcolor.DataSource = Enum.GetNames(typeof(KnownColor));
            if (hudcolor != null)
            {
                int index = CMB_osdcolor.Items.IndexOf(hudcolor);
                CMB_osdcolor.SelectedIndex = index;
            }
            else
            {
                int index = CMB_osdcolor.Items.IndexOf("White");
                CMB_osdcolor.SelectedIndex = index;
            }

            // set distance/speed unit states
            CMB_distunits.DataSource = Enum.GetNames(typeof(Common.distances));
            CMB_speedunits.DataSource = Enum.GetNames(typeof(Common.speeds));
            if (MainV2.config["distunits"] != null)
                CMB_distunits.Text = MainV2.config["distunits"].ToString();
            if (MainV2.config["speedunits"] != null)
                CMB_speedunits.Text = MainV2.config["speedunits"].ToString();

            // setup language selection
            CultureInfo ci = null;
            foreach (string name in new string[] { "en-US", "zh-Hans" })
            {
                ci = MainV2.getcultureinfo(name);
                if (ci != null)
                    languages.Add(ci);
            }

            CMB_language.DisplayMember = "DisplayName";
            CMB_language.DataSource = languages;
            bool match = false;
            for (int i = 0; i < languages.Count && !match; i++)
            {
                ci = Thread.CurrentThread.CurrentUICulture;
                while (!ci.Equals(CultureInfo.InvariantCulture))
                {
                    if (ci.Equals(languages[i]))
                    {
                        CMB_language.SelectedIndex = i;
                        match = true;
                        break;
                    }
                    ci = ci.Parent;
                }
            }
            CMB_language.SelectedIndexChanged += CMB_language_SelectedIndexChanged;

            startup = false;
        }

        string[] genpids()
        {
            List<string> temp = new List<string>();
            // pids
            for (double a = 8.00; a >= -0.001; a -= 0.001)
            {
                temp.Add(a.ToString("0.0##"));
            }

            // Nav angles + throttle
            for (int a = 100; a >= -90; a -= 1)
            {
                temp.Add(a.ToString("0.0#"));
            }

            // imax
            for (int a = 8000; a >= -4500; a -= 100)
            {
                temp.Add(a.ToString("0.0#"));
            }

            // FS pulse
            for (int a = 1200; a >= 900; a -= 1)
            {
                temp.Add(a.ToString("0.0#"));
            }

            return temp.ToArray();
        }

        void readToolTips()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Configuration));

            string data = resources.GetString("MAVParam");
            string[] tips = data.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var tip in tips)
            {
                if (!tip.StartsWith("||"))
                    continue;

                string[] cols = tip.Split(new string[] { "||" }, 9, StringSplitOptions.None);

                if (cols.Length >= 8)
                {
                    paramsettings param = new paramsettings();
                    try
                    {
                        param.name = cols[1];
                        param.desc = AddNewLinesForTooltip(cols[7]);
                        param.scale = float.Parse(cols[5]);
                        param.minvalue = float.Parse(cols[2]);
                        param.maxvalue = float.Parse(cols[3]);
                        param.normalvalue = float.Parse(cols[4]);
                    }
                    catch { }
                    tooltips[cols[1]] = param;
                }

            }
        }

        // from http://stackoverflow.com/questions/2512781/winforms-big-paragraph-tooltip/2512895#2512895
        private const int maximumSingleLineTooltipLength = 50;

        private static string AddNewLinesForTooltip(string text)
        {
            if (text.Length < maximumSingleLineTooltipLength)
                return text;
            int lineLength = (int)Math.Sqrt((double)text.Length) * 2;
            StringBuilder sb = new StringBuilder();
            int currentLinePosition = 0;
            for (int textIndex = 0; textIndex < text.Length; textIndex++)
            {
                // If we have reached the target line length and the next      
                // character is whitespace then begin a new line.   
                if (currentLinePosition >= lineLength &&
                    char.IsWhiteSpace(text[textIndex]))
                {
                    sb.Append(Environment.NewLine);
                    currentLinePosition = 0;
                }
                // If we have just started a new line, skip all the whitespace.    
                if (currentLinePosition == 0)
                    while (textIndex < text.Length && char.IsWhiteSpace(text[textIndex]))
                        textIndex++;
                // Append the next character.     
                if (textIndex < text.Length) sb.Append(text[textIndex]);
                currentLinePosition++;
            }
            return sb.ToString();
        }

        internal void processToScreen()
        {
            Params.Rows.Clear();

            // process hashdefines and update display
            foreach (string value in param.Keys)
            {
                if (value == null || value == "")
                    continue;

                //System.Diagnostics.Debug.WriteLine("Doing: " + value);

                Params.Rows.Add();
                Params.Rows[Params.RowCount - 1].Cells[Command.Index].Value = value;
                Params.Rows[Params.RowCount - 1].Cells[Value.Index].Value = ((float)param[value]).ToString("0.###");
                try
                {
                    if (tooltips[value] != null)
                    {
                        Params.Rows[Params.RowCount - 1].Cells[Command.Index].ToolTipText = ((paramsettings)tooltips[value]).desc;
                        Params.Rows[Params.RowCount - 1].Cells[RawValue.Index].ToolTipText = ((paramsettings)tooltips[value]).desc;
                        Params.Rows[Params.RowCount - 1].Cells[Value.Index].ToolTipText = ((paramsettings)tooltips[value]).desc;

                        Params.Rows[Params.RowCount - 1].Cells[Default.Index].Value = ((paramsettings)tooltips[value]).normalvalue;
                        Params.Rows[Params.RowCount - 1].Cells[mavScale.Index].Value = ((paramsettings)tooltips[value]).scale;
                        Params.Rows[Params.RowCount - 1].Cells[Value.Index].Value = float.Parse(Params.Rows[Params.RowCount - 1].Cells[RawValue.Index].Value.ToString()) / float.Parse(Params.Rows[Params.RowCount - 1].Cells[mavScale.Index].Value.ToString());
                    }
                }
                catch { }

                string name = value;
                Control[] text = this.Controls.Find(name, true);
                foreach (Control ctl in text)
                {
                    try
                    {
                        ((DomainUpDown)ctl).Items.AddRange(genpids());
                        string option = ((float)param[value]).ToString("0.0##");
                        int index = ((DomainUpDown)ctl).Items.IndexOf(option);
                        ((DomainUpDown)ctl).BackColor = Color.FromArgb(0x43, 0x44, 0x45);
                        Console.WriteLine(name + " " + option + " " + index + " " + ((float)param[value]));
                        ((DomainUpDown)ctl).Validated += null;
                        if (index == -1)
                        {
                            ((DomainUpDown)ctl).Text = ((float)param[value]).ToString("0.0##");
                        }
                        else
                        {
                            ((DomainUpDown)ctl).SelectedIndex = index;
                        }
                        if (tooltips[value] != null)
                        {
                            try
                            {
                                toolTip1.SetToolTip(ctl, tooltips[value].ToString());
                            }
                            catch { }
                        }
                        ((DomainUpDown)ctl).Validated += new EventHandler(EEPROM_View_float_TextChanged);
                    }
                    catch { }

                }
                if (text.Length == 0)
                {
                    Console.WriteLine(name + " not found");
                }

            }
            Params.Sort(Params.Columns[0], ListSortDirection.Ascending);
        }

        void Configuration_Validating(object sender, CancelEventArgs e)
        {
            EEPROM_View_float_TextChanged(sender, e);
        }

        internal void EEPROM_View_float_TextChanged(object sender, EventArgs e)
        {
            float value = 0;
            string name = ((Control)sender).Name;

            // do domainupdown state check
            try
            {
                value = float.Parse(((Control)sender).Text);
                changes[name] = value;
                ((Control)sender).BackColor = Color.Green;
            }
            catch (Exception)
            {
                ((Control)sender).BackColor = Color.Red;
            }

            try
            {
                // enable roll and pitch pairing for ac2
                if (CHK_lockrollpitch.Checked)
                {
                    if (name.StartsWith("RATE_") || name.StartsWith("STB_"))
                    {
                        if (name.Contains("_RLL_"))
                        {
                            string newname = name.Replace("_RLL_", "_PIT_");
                            foreach (DataGridViewRow row in Params.Rows)
                            {
                                if (row.Cells[0].Value.ToString() == newname)
                                {
                                    row.Cells[1].Value = float.Parse(((Control)sender).Text);
                                    break;
                                }
                            }
                        }
                        else if (name.Contains("_PIT_"))
                        {
                            string newname = name.Replace("_PIT_", "_RLL_");
                            foreach (DataGridViewRow row in Params.Rows)
                            {
                                if (row.Cells[0].Value.ToString() == newname)
                                {
                                    row.Cells[1].Value = float.Parse(((Control)sender).Text);
                                    break;
                                }
                            }
                        }
                    }
                }
                // keep nav_lat and nav_lon paired
                if (name.Contains("NAV_LAT_"))
                {
                    string newname = name.Replace("NAV_LAT_", "NAV_LON_");
                    foreach (DataGridViewRow row in Params.Rows)
                    {
                        if (row.Cells[0].Value.ToString() == newname)
                        {
                            row.Cells[1].Value = float.Parse(((Control)sender).Text);
                            break;
                        }
                    }
                }
                // keep nav_lat and nav_lon paired
                if (name.Contains("HLD_LAT_"))
                {
                    string newname = name.Replace("HLD_LAT_", "HLD_LON_");
                    foreach (DataGridViewRow row in Params.Rows)
                    {
                        if (row.Cells[0].Value.ToString() == newname)
                        {
                            row.Cells[1].Value = float.Parse(((Control)sender).Text);
                            break;
                        }
                    }
                }
            }
            catch { }

            try
            {
                // set param table as well
                foreach (DataGridViewRow row in Params.Rows)
                {
                    if (row.Cells[0].Value.ToString() == name)
                    {
                        row.Cells[1].Value = float.Parse(((Control)sender).Text);
                        break;
                    }
                }
            }
            catch { }
            //((Control)sender).Focus();
        }

        void Params_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex == -1 || e.ColumnIndex == -1 || startup == true || e.ColumnIndex != 1)
                return;
            try
            {
                if (Params[Command.Index, e.RowIndex].Value.ToString().EndsWith("_REV") && (Params[Command.Index, e.RowIndex].Value.ToString().StartsWith("RC") || Params[Command.Index, e.RowIndex].Value.ToString().StartsWith("HS")))
                {
                    if (Params[e.ColumnIndex, e.RowIndex].Value.ToString() == "0")
                        Params[e.ColumnIndex, e.RowIndex].Value = "-1";
                }

                Params[e.ColumnIndex, e.RowIndex].Style.BackColor = Color.Green;
                changes[Params[0, e.RowIndex].Value] = float.Parse(Params[e.ColumnIndex, e.RowIndex].Value.ToString());
            }
            catch (Exception)
            {
                Params[e.ColumnIndex, e.RowIndex].Style.BackColor = Color.Red;
            }

            try
            {
                // set control as well
                Control[] text = this.Controls.Find(Params[0, e.RowIndex].Value.ToString(), true);
                if (text.Length > 0)
                {
                    string option = (float.Parse(Params[e.ColumnIndex, e.RowIndex].Value.ToString())).ToString("0.0##", System.Globalization.CultureInfo.CurrentCulture);
                    int index = ((DomainUpDown)text[0]).Items.IndexOf(option);
                    if (index != -1)
                    {
                        ((DomainUpDown)text[0]).SelectedIndex = index;
                        ((DomainUpDown)text[0]).BackColor = Color.Green;
                    }
                }
            }
            catch { }

            Params.Focus();
        }

        private void BUT_load_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.AddExtension = true;
            ofd.DefaultExt = ".param";
            ofd.RestoreDirectory = true;
            ofd.Filter = "Param List|*.param";
            DialogResult dr = ofd.ShowDialog();
            if (dr == DialogResult.OK)
            {
                StreamReader sr = new StreamReader(ofd.OpenFile());
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();

                    if (line.Contains("NOTE:"))
                        MessageBox.Show(line, "Saved Note");

                    int index = line.IndexOf(',');

                    if (index == -1)
                        continue;

                    string name = line.Substring(0, index);
                    float value = float.Parse(line.Substring(index + 1), new System.Globalization.CultureInfo("en-US"));

                    // set param table as well
                    foreach (DataGridViewRow row in Params.Rows)
                    {
                        if (name == "SYSID_SW_MREV")
                            continue;
                        if (name == "WP_TOTAL")
                            continue;
                        if (row.Cells[0].Value.ToString() == name)
                        {
                            if (row.Cells[1].Value.ToString() != value.ToString())
                                row.Cells[1].Value = value;
                            break;
                        }
                    }
                }
                sr.Close();
            }
        }

        private void BUT_save_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.DefaultExt = ".param";
            sfd.RestoreDirectory = true;
            sfd.Filter = "Param List|*.param";
            DialogResult dr = sfd.ShowDialog();
            if (dr == DialogResult.OK)
            {
                StreamWriter sw = new StreamWriter(sfd.OpenFile());
                string input = DateTime.Now + " Frame : + | Arducopter Kit | Kit motors";
                if (MainV2.APMFirmware == MainV2.Firmwares.ArduPilotMega)
                {
                    input = DateTime.Now + " Plane: Skywalker";
                }
                Common.InputBox("Custom Note", "Enter your Notes/Frame Type etc", ref input);
                if (input != "")
                    sw.WriteLine("NOTE: " + input.Replace(',', '|'));
                foreach (DataGridViewRow row in Params.Rows)
                {
                    sw.WriteLine(row.Cells[0].Value.ToString() + "," + float.Parse(row.Cells[1].Value.ToString()).ToString(new System.Globalization.CultureInfo("en-US")));
                }
                sw.Close();
            }
        }

        private void BUT_writePIDS_Click(object sender, EventArgs e)
        {
            foreach (string value in changes.Keys)
            {
                try
                {
                    MainV2.comPort.setParam(value, (float)changes[value]);

                    try
                    {
                        // set control as well
                        Control[] text = this.Controls.Find(value, true);
                        if (text.Length > 0)
                        {
                            ((DomainUpDown)text[0]).BackColor = Color.FromArgb(0x43, 0x44, 0x45);
                        }
                    }
                    catch { }

                    try
                    {
                        // set param table as well
                        foreach (DataGridViewRow row in Params.Rows)
                        {
                            if (row.Cells[0].Value.ToString() == value)
                            {
                                row.Cells[1].Style.BackColor = Color.FromArgb(0x43, 0x44, 0x45);
                                break;
                            }
                        }
                    }
                    catch { }

                }
                catch { MessageBox.Show("Set " + value + " Failed"); }
            }

            changes.Clear();
        }

        const float rad2deg = (float)(180 / Math.PI);
        const float deg2rad = (float)(1.0 / rad2deg);

        private void Planner_TabIndexChanged(object sender, EventArgs e)
        {
            if (ConfigTabs.SelectedTab == TabSetup)
            {
                if (!MainV2.comPort.BaseStream.IsOpen)
                {
                    MessageBox.Show("Please Connect First");
                    ConfigTabs.SelectedIndex = 0;
                }
                else
                {

                    Setup.Setup temp = new Setup.Setup();

                    temp.Configuration = this;

                    MainV2.fixtheme(temp);

                    TabSetup.Controls.Clear();

                    TabSetup.Controls.Add(temp.Controls[0]);
                }
            }
        }

        private void BUT_videostart_Click(object sender, EventArgs e)
        {
            // stop first
            BUT_videostop_Click(sender, e);

            try
            {
                MainV2.cam = new WebCamService.Capture(CMB_videosources.SelectedIndex, 0, 0, 0);

                MainV2.cam.showhud = CHK_hudshow.Checked;

                MainV2.cam.Start();

                BUT_videostart.Enabled = false;
            }
            catch (Exception ex) { MessageBox.Show("Camera Fail: " + ex.Message); }

        }

        private void BUT_videostop_Click(object sender, EventArgs e)
        {
            BUT_videostart.Enabled = true;
            if (MainV2.cam != null)
            {
                MainV2.cam.Dispose();
                MainV2.cam = null;
            }
        }

        private void CMB_videosources_MouseClick(object sender, MouseEventArgs e)
        {
            // the reason why i dont populate this list is because on linux/mac this call will fail.
            WebCamService.Capture capt = new WebCamService.Capture();

            List<string> devices = WebCamService.Capture.getDevices();

            CMB_videosources.DataSource = devices;

            capt.Dispose();
        }

        private void CHK_hudshow_CheckedChanged(object sender, EventArgs e)
        {
            GCSViews.FlightData.myhud.hudon = CHK_hudshow.Checked;
        }

        private void CHK_enablespeech_CheckedChanged(object sender, EventArgs e)
        {
            MainV2.speechenable = CHK_enablespeech.Checked;
            MainV2.config["speechenable"] = CHK_enablespeech.Checked;
            if (MainV2.talk != null)
                MainV2.talk.SpeakAsyncCancelAll();
        }
        private void CMB_language_SelectedIndexChanged(object sender, EventArgs e)
        {
            MainV2.instance.changelanguage((CultureInfo)CMB_language.SelectedItem);

#if !DEBUG
                MessageBox.Show("Please Restart the Planner");

                Application.Exit();
#endif
        }

        private void CMB_osdcolor_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (startup)
                return;
            if (CMB_osdcolor.Text != "")
            {
                MainV2.config["hudcolor"] = CMB_osdcolor.Text;
                GCSViews.FlightData.myhud.hudcolor = Color.FromKnownColor((KnownColor)Enum.Parse(typeof(KnownColor), CMB_osdcolor.Text));
            }
        }

        private void CHK_speechwaypoint_CheckedChanged(object sender, EventArgs e)
        {
            if (startup)
                return;
            MainV2.config["speechwaypointenabled"] = ((CheckBox)sender).Checked.ToString();

            if (((CheckBox)sender).Checked)
            {
                string speechstring = "Heading to Waypoint {wpn}";
                if (MainV2.config["speechwaypoint"] != null)
                    speechstring = MainV2.config["speechwaypoint"].ToString();
                Common.InputBox("Notification", "What do you want it to say?", ref speechstring);
                MainV2.config["speechwaypoint"] = speechstring;
            }
        }

        private void CHK_speechmode_CheckedChanged(object sender, EventArgs e)
        {
            if (startup)
                return;
            MainV2.config["speechmodeenabled"] = ((CheckBox)sender).Checked.ToString();

            if (((CheckBox)sender).Checked)
            {
                string speechstring = "Mode changed to {mode}";
                if (MainV2.config["speechmode"] != null)
                    speechstring = MainV2.config["speechmode"].ToString();
                Common.InputBox("Notification", "What do you want it to say?", ref speechstring);
                MainV2.config["speechmode"] = speechstring;
            }
        }

        private void CHK_speechcustom_CheckedChanged(object sender, EventArgs e)
        {
            if (startup)
                return;
            MainV2.config["speechcustomenabled"] = ((CheckBox)sender).Checked.ToString();

            if (((CheckBox)sender).Checked)
            {
                string speechstring = "Heading to Waypoint {wpn}, altitude is {alt}, Ground speed is {gsp} ";
                if (MainV2.config["speechcustom"] != null)
                    speechstring = MainV2.config["speechcustom"].ToString();
                Common.InputBox("Notification", "What do you want it to say?", ref speechstring);
                MainV2.config["speechcustom"] = speechstring;
            }
        }

        private void BUT_rerequestparams_Click(object sender, EventArgs e)
        {
            if (!MainV2.comPort.BaseStream.IsOpen)
                return;
            ((MyButton)sender).Enabled = false;
            try
            {
                MainV2.comPort.getParamList();
            }
            catch { MessageBox.Show("Error: getting param list"); }

            ((MyButton)sender).Enabled = true;
            startup = true;
            Configuration_Load(null, null);
        }

        private void CHK_speechbattery_CheckedChanged(object sender, EventArgs e)
        {
            if (startup)
                return;
            MainV2.config["speechbatteryenabled"] = ((CheckBox)sender).Checked.ToString();

            if (((CheckBox)sender).Checked)
            {
                string speechstring = "WARNING, Battery at {batv} Volt";
                if (MainV2.config["speechbattery"] != null)
                    speechstring = MainV2.config["speechbattery"].ToString();
                Common.InputBox("Notification", "What do you want it to say?", ref speechstring);
                MainV2.config["speechbattery"] = speechstring;

                speechstring = "9.6";
                if (MainV2.config["speechbatteryvolt"] != null)
                    speechstring = MainV2.config["speechbatteryvolt"].ToString();
                Common.InputBox("Battery Level", "What Voltage do you want to warn at?", ref speechstring);
                MainV2.config["speechbatteryvolt"] = speechstring;

            }
        }

        private void BUT_Joystick_Click(object sender, EventArgs e)
        {
            Form joy = new JoystickSetup();
            MainV2.fixtheme(joy);
            joy.Show();
        }

        private void CMB_distunits_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (startup)
                return;
            MainV2.config["distunits"] = CMB_distunits.Text;
            MainV2.instance.changeunits();
        }

        private void CMB_speedunits_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (startup)
                return;
            MainV2.config["speedunits"] = CMB_speedunits.Text;
            MainV2.instance.changeunits();
        }



        private void CMB_rateattitude_SelectedIndexChanged(object sender, EventArgs e)
        {
            MainV2.config[((ComboBox)sender).Name] = ((ComboBox)sender).Text;
            MainV2.cs.rateattitude = byte.Parse(((ComboBox)sender).Text);
        }

        private void CMB_rateposition_SelectedIndexChanged(object sender, EventArgs e)
        {
            MainV2.config[((ComboBox)sender).Name] = ((ComboBox)sender).Text;
            MainV2.cs.rateposition = byte.Parse(((ComboBox)sender).Text);
        }

        private void CMB_ratestatus_SelectedIndexChanged(object sender, EventArgs e)
        {
            MainV2.config[((ComboBox)sender).Name] = ((ComboBox)sender).Text;
            MainV2.cs.ratestatus = byte.Parse(((ComboBox)sender).Text);
        }

        private void CMB_raterc_SelectedIndexChanged(object sender, EventArgs e)
        {
            MainV2.config[((ComboBox)sender).Name] = ((ComboBox)sender).Text;
            MainV2.cs.raterc = byte.Parse(((ComboBox)sender).Text);
        }

        private void CHK_mavdebug_CheckedChanged(object sender, EventArgs e)
        {
            MainV2.comPort.debugmavlink = CHK_mavdebug.Checked;
        }

        private void CHK_resetapmonconnect_CheckedChanged(object sender, EventArgs e)
        {
            MainV2.config[((CheckBox)sender).Name] = ((CheckBox)sender).Checked.ToString();
        }

        private void CHK_speechaltwarning_CheckedChanged(object sender, EventArgs e)
        {
            if (startup)
                return;
            MainV2.config["speechaltenabled"] = ((CheckBox)sender).Checked.ToString();

            if (((CheckBox)sender).Checked)
            {
                string speechstring = "WARNING, low altitude {alt}";
                if (MainV2.config["speechalt"] != null)
                    speechstring = MainV2.config["speechalt"].ToString();
                Common.InputBox("Notification", "What do you want it to say?", ref speechstring);
                MainV2.config["speechalt"] = speechstring;

                speechstring = "2";
                if (MainV2.config["speechaltheight"] != null)
                    speechstring = MainV2.config["speechaltheight"].ToString();
                Common.InputBox("Min Alt", "What altitude do you want to warn at? (relative to home)", ref speechstring);
                MainV2.config["speechaltheight"] = (double.Parse(speechstring) / MainV2.cs.multiplierdist).ToString(); // save as m

            }
        }

        private void CMB_osdcolor_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index < 0)
                return;

            Graphics g = e.Graphics;
            Rectangle rect = e.Bounds;
            Brush brush = null;

            if ((e.State & DrawItemState.Selected) == 0)
                brush = new SolidBrush(CMB_osdcolor.BackColor);
            else
                brush = SystemBrushes.Highlight;

            g.FillRectangle(brush, rect);

            brush = new SolidBrush(Color.FromName((string)CMB_osdcolor.Items[e.Index]));

            g.FillRectangle(brush, rect.X + 2, rect.Y + 2, 30, rect.Height - 4);
            g.DrawRectangle(Pens.Black, rect.X + 2, rect.Y + 2, 30, rect.Height - 4);

            if ((e.State & DrawItemState.Selected) == 0)
                brush = new SolidBrush(CMB_osdcolor.ForeColor);
            else
                brush = SystemBrushes.HighlightText;
            g.DrawString(CMB_osdcolor.Items[e.Index].ToString(),
                CMB_osdcolor.Font, brush, rect.X + 35, rect.Top + rect.Height - CMB_osdcolor.Font.Height);
        }

        private void NUM_tracklength_ValueChanged(object sender, EventArgs e)
        {
            MainV2.config["NUM_tracklength"] = NUM_tracklength.Value.ToString();

        }

        private void CHK_loadwponconnect_CheckedChanged(object sender, EventArgs e)
        {
            MainV2.config["loadwpsonconnect"] = CHK_loadwponconnect.Checked.ToString();
        }

        private void BUT_compare_Click(object sender, EventArgs e)
        {
            Hashtable param2 = new Hashtable();

            OpenFileDialog ofd = new OpenFileDialog();
            ofd.AddExtension = true;
            ofd.DefaultExt = ".param";
            ofd.RestoreDirectory = true;
            ofd.Filter = "Param List|*.param";
            DialogResult dr = ofd.ShowDialog();
            if (dr == DialogResult.OK)
            {
                StreamReader sr = new StreamReader(ofd.OpenFile());
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();

                    if (line.Contains("NOTE:"))
                        MessageBox.Show(line, "Saved Note");

                    int index = line.IndexOf(',');

                    if (index == -1)
                        continue;

                    string name = line.Substring(0, index);
                    float value = float.Parse(line.Substring(index + 1), new System.Globalization.CultureInfo("en-US"));

                    if (name == "SYSID_SW_MREV")
                        continue;
                    if (name == "WP_TOTAL")
                        continue;

                    param2[name] = value;
                }
                sr.Close();

                ParamCompare temp = new ParamCompare(this, param, param2);
                MainV2.fixtheme(temp);
                temp.ShowDialog();
            }
        }
    }
}