using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Globalization;
using System.Resources;


namespace EduNetworkBuilder
{
    public partial class ListBoxWindow : Form
    {
        class MyPuzzleEntry
        {
            public string Title;
            public string PuzzleName;
            public bool isdone = false;
            public string level = "";
            public bool InRegressionMode = false;
            public bool HasTest = false;
            public bool PassedTest = false;
            public bool FailedTest = false;

            public override string ToString()
            {
                string donstr = "";
                if (InRegressionMode)
                {
                    if (HasTest) donstr = "+ ";
                    else donstr = "- ";
                    if (PassedTest) donstr = "$ ";
                    if (FailedTest) donstr = "X ";
                    return donstr + level + " " + this.Title;
                }
                else
                {
                    if (isdone) donstr = "* ";
                    return donstr + level + " " + this.Title;
                }
            }
        }

        protected LBContents MyMode = LBContents.messages;
        protected DebugLevel WhatToDisplay = DebugLevel.info; //used when viewing packet-messages
        NetworkDevice myNetDevice;
        PacketMessage myPacketMessage;
        int EditableCount = -1;
        bool processing = false;
        string FilterString = "";
        string TestString = "Test";
        string NoTestString = "No Test";
        string PassedString = "Passed";
        string FailedString = "Failed";
        string Untested = "Untested";
        public bool ClosingRegression = false;


        /// <summary>
        /// Instantiate a ListBoxWindow for use in choosing a network to load
        /// </summary>
        public ListBoxWindow()
        {
            InitializeComponent();
            LanguagifyComponents();
            MyMode = LBContents.puzzles;

            UpdateForm();
            CheckBox newCB;
            btnAdd.Visible = false;
            int count = 0;
            lblInstructions.Text = NB.Translate("LBW_LBWFilter");
            panelCheckboxes.SuspendLayout();
            string SelectedTag = GetSelectedTag();
            tbSearchBox.Visible = true;
            if (SelectedTag == NB.Translate("_All"))
                Text = Text + NB.Translate("_AllS");

            NBSettings oursettings = NB.GetSettings();

            foreach (string str in NB.GetPuzzleTags())
            {
                newCB = AddCheckBox(count, str);
                if (str == SelectedTag || (SelectedTag == "ALL" && Regex.IsMatch(str,"Level")))
                {
                    newCB.Checked = true; //The first level with an unsolved puzzle starts checked
                }
                else
                {
                    newCB.Checked = false;
                }
                count++;
            }
            panelCheckboxes.ResumeLayout();
            btnOK.Text = NB.Translate("_Load");
            btnAdd.Text = NB.Translate("_Cancel");
            btnAdd.Visible = true;
            cbLoadPuzzlesAtStart.Checked = oursettings.AutoStartPuzzles;
            Text = NB.Translate("NB_puzzlesToolStripMenuItem"); //"Puzzles
            UpdateForm();
        }

        /// <summary>
        /// We are doing a routing table or dhcp.  We pass it the device and pull the data from that
        /// </summary>
        /// <param name="MasterDevice">The master device to edit/view the routing table of</param>
        public ListBoxWindow(NetworkDevice MasterDevice, LBContents mode)
        {
            InitializeComponent();
            LanguagifyComponents();
            tbSearchBox.Visible = false;
            if (mode == LBContents.routes)
            {
                MyMode = LBContents.routes;
                myNetDevice = MasterDevice;
                lblInstructions.Text = NB.Translate("LBW_LBWDblClckRout");
                lbWindowData.Font = new System.Drawing.Font("Courier New", 8);
                btnAdd.Visible = true;
                Text = NB.Translate("DC_btnRoutes"); //Routes
            }
            if (mode == LBContents.dhcp)
            {
                MyMode = LBContents.dhcp;
                myNetDevice = MasterDevice;
                lblInstructions.Text = NB.Translate("LBW_LBWDblClckIf");
                lbWindowData.Font = new System.Drawing.Font("Courier New", 8);
                btnAdd.Visible = false;
                Text = NB.Translate("H_DHCP_Title"); //DHCP
            }
            if(mode == LBContents.regressiontest)
            {
                MyMode = LBContents.regressiontest;
                //Regression testing.  Similar to listing all the puzzles.
                Text = NB.Translate("LBW_Regression_Testing"); //Regression Testing
                                                               //
                lblInstructions.Text = "";
                UpdateForm();
                CheckBox newCB;
                int count = 0;

                panelCheckboxes.SuspendLayout();
                string SelectedTag = GetSelectedTag();
                tbSearchBox.Visible = true;
                if (SelectedTag == NB.Translate("_All"))
                    Text = Text + NB.Translate("_AllS");

                NBSettings oursettings = NB.GetSettings();

                foreach (string str in NB.GetPuzzleTags())
                {
                    newCB = AddCheckBox(count, str);
                    count++;
                }
                newCB = AddCheckBox(count++, TestString);
                newCB = AddCheckBox(count++, NoTestString);
                newCB = AddCheckBox(count++, PassedString);
                newCB = AddCheckBox(count++, FailedString);
                newCB.Checked = true; //start with "Failed" checked
                newCB = AddCheckBox(count++, Untested);
                newCB.Checked = true; //start with "Untested" checked

                this.ControlBox = false; //remove the X at the top corner that gives us problems

                panelCheckboxes.ResumeLayout();
                btnOK.Text = NB.Translate("_Load");
                btnAdd.Text = NB.Translate("_Cancel");
                btnAdd.Visible = true;
            }
            UpdateForm();
        }

        /// <summary>
        /// We are doing a packet message detail look.   
        /// </summary>
        /// <param name="Messages">The packet message to look at</param>
        public ListBoxWindow(PacketMessage Messages)
        {
            InitializeComponent();
            LanguagifyComponents();
            MyMode = LBContents.messages;
            myPacketMessage = Messages;
            UpdateForm();
            btnAdd.Visible = false;
            int count=0;
            lblInstructions.Text = NB.Translate("LBW_LBWDetail");
            panelCheckboxes.SuspendLayout();
            Text = NB.Translate("H_Packet_Title"); //Packet
            foreach (string str in Enum.GetNames(typeof(DebugLevel)))
            {
                AddCheckBox(count, str);
                count++;
            }
            panelCheckboxes.ResumeLayout();
            UpdateChecked();
        }

        private void LanguagifyComponents()
        {
            Text = NB.Translate("_OK");
            Text = NB.Translate("LBW_lblInstructions");
            Text = NB.Translate("LBW_btnAdd");
            Text = NB.Translate("LBW_cbLoadPuzzlesAtStart");
            Text = NB.Translate("LBW_btnReset");
            Text = NB.Translate("LBW_Form");
        }

        private CheckBox AddCheckBox(int count, string name)
        {
            int myY = 1;
            int myX = 1;
            int cdwidth = 70;
            int cdHeight = 20;
            int divisor = panelCheckboxes.Width / cdwidth;
            myX = (cdwidth * count) % (divisor * cdwidth);
            myY = ((cdwidth * count) / (divisor * cdwidth)) * cdHeight;
            CheckBox newCB = new CheckBox();
            newCB.Text = name;
            Point mylocation = new Point(myX, myY);
            newCB.AutoSize = true;
            newCB.Name = "checkBox" + count.ToString();
            newCB.Size = new System.Drawing.Size(98, 21);
            newCB.TabIndex = count;
            newCB.UseVisualStyleBackColor = true;
            newCB.Location = mylocation;            
            newCB.CheckedChanged += genericCheckmarkChange;
            panelCheckboxes.Controls.Add(newCB);
            return newCB;
        }

        private string GetSelectedTag()
        {
            PuzzleInfo PI;
            string first = "";
            NBSettings oursettings = NB.GetSettings();

            string OriginalChoice = oursettings.ProcessingLevel;
            if(OriginalChoice != null)
            {
                if (NB.PuzzleLevelHasUnsolved(OriginalChoice))
                    return OriginalChoice;
            }

            foreach (string str in NB.GetPuzzleNames())
            {
                if(!oursettings.ScoreList.Contains(str))
                {
                    PI = NB.GetPuzzleInfoFromName(str);
                    first = PI.strLevel;
                    break;
                }
            }
            if (first != "")
                return first;
            return NB.Translate("_All");
        }

        private void UpdateForm()
        {
            int selectedIndex = lbWindowData.SelectedIndex;
            int FirstUnfinishedIndex = -1;

            string selected = "";
            int topmost = lbWindowData.TopIndex;
            int totalcount = lbWindowData.Items.Count;
            if (lbWindowData.SelectedIndex != -1)
                selected = lbWindowData.Items[lbWindowData.SelectedIndex].ToString();
            lbWindowData.Items.Clear();
            cbLoadPuzzlesAtStart.Visible = false;
            btnReset.Visible = false;
            List<string> itemstrings = new List<string>();
            if (MyMode == LBContents.messages)
            {
                itemstrings.AddRange(myPacketMessage.GetMessagesSummary());
                itemstrings.AddRange(myPacketMessage.GetMessagesLike(WhatToDisplay));
                foreach (string str in itemstrings)
                {
                    lbWindowData.Items.Add(str);
                }
            }
            if(MyMode == LBContents.routes)
            {
                itemstrings.Add(NB.Translate("LBW_UpdateFormStatRout"));
                itemstrings.AddRange(myNetDevice.DeviceRouteStrings());
                EditableCount = itemstrings.Count();
                itemstrings.Add(NB.Translate("LBW_UpdateFormNICRout"));
                itemstrings.AddRange(myNetDevice.NICRouteStrings());
                foreach (string str in itemstrings)
                {
                    lbWindowData.Items.Add(str);
                }
            }
            if (MyMode == LBContents.dhcp)
            {
                myNetDevice.CheckDHCPRangesAgainstInterfaces();
                itemstrings.AddRange(myNetDevice.DHCPStrings());
                foreach (string str in itemstrings)
                {
                    lbWindowData.Items.Add(str);
                }
            }
            if (MyMode == LBContents.puzzles)
            {
                cbLoadPuzzlesAtStart.Visible = true;
                btnReset.Visible = true;
                PuzzleInfo pi;
                string shown_name;
                string puzzle_name="";
                List<string> Puzzles = NB.GetPuzzleNames();
                NBSettings oursettings = NB.GetSettings();
                if (Puzzles == null) return;
                bool wasfinished = false;
                foreach (string str in Puzzles)
                {
                    wasfinished = false;
                    if (FilterString == "")
                    {
                        pi = NB.GetPuzzleInfoFromName(str);
                        //shown_name = pi.PuzzleName;
                        shown_name = pi.NetTitle.GetText();
                        puzzle_name = pi.PuzzleName;
                        if (oursettings.CheckIfDone(str))
                        {
                            wasfinished = true;
                        }
                        foreach (string tag in pi.PuzzleTags)
                        {
                            if (isChecked(tag))
                            {
                                MyPuzzleEntry MPE = new MyPuzzleEntry();
                                MPE.PuzzleName = puzzle_name;
                                MPE.Title = shown_name;
                                MPE.isdone = wasfinished;
                                MPE.level = tag;
                                if(selected == "" && !wasfinished)   selected = shown_name; //Select the first unfinished puzzle
                                lbWindowData.Items.Add(MPE);
                                break;
                            }
                        }
                        if (!wasfinished && FirstUnfinishedIndex == -1)
                            FirstUnfinishedIndex = lbWindowData.Items.Count - 1;
                    }
                    else
                    {
                        //We are filtering stuff
                        pi = NB.GetPuzzleInfoFromName(str);
                        //shown_name = pi.PuzzleName;
                        shown_name = pi.NetTitle.GetText();
                        bool added = false;
                        string localFilter = ".*" + FilterString + ".*";
                        if (oursettings.ScoreList.Contains(str))
                        {
                            wasfinished = true;
                        }
                        MyPuzzleEntry MPE = new MyPuzzleEntry();
                        MPE.PuzzleName = puzzle_name;
                        MPE.Title = shown_name;
                        MPE.isdone = wasfinished;
                        MPE.level = "Level_" + pi.Level;

                        if (!added && pi.PuzzleName != null && Regex.IsMatch(pi.PuzzleName, localFilter, RegexOptions.IgnoreCase))
                        {
                            added = true;
                            lbWindowData.Items.Add(MPE);
                        }
                        if (!added && pi.PuzzleDescription!= null && Regex.IsMatch(pi.PuzzleDescription, localFilter, RegexOptions.IgnoreCase))
                        {
                            added = true;
                            lbWindowData.Items.Add(MPE);
                        }
                        if (!added && pi.PuzzleTitle != null && Regex.IsMatch(pi.PuzzleTitle, localFilter,RegexOptions.IgnoreCase))
                        {
                            added = true;
                            lbWindowData.Items.Add(MPE);
                        }
                        foreach (string tag in pi.PuzzleTags)
                        {
                            if (!added && pi.PuzzleTitle != null && Regex.IsMatch(tag, localFilter, RegexOptions.IgnoreCase))
                            {
                                if (selected == "" && !wasfinished) selected = shown_name; //Select the first unfinished puzzle
                                lbWindowData.Items.Add(MPE);
                                break;
                            }
                        }
                    }
                }
                if(selected != null && selected != "")
                {
                    if (selectedIndex >= 0 && selectedIndex < lbWindowData.Items.Count)
                    {
                        lbWindowData.SelectedIndex = selectedIndex;
                        lbWindowData.TopIndex = topmost;
                    }
                }
                if(lbWindowData.SelectedIndex == -1 && FirstUnfinishedIndex != -1 )
                {
                    if(lbWindowData.Items.Count > FirstUnfinishedIndex)
                        lbWindowData.SelectedIndex = FirstUnfinishedIndex; //Select the first unselected item if nothing else was selected
                }
                if(lbWindowData.SelectedIndex != -1)
                {
                    btnOK.Enabled = true;
                }
                else
                {
                    btnOK.Enabled = false;
                }
            }
            if (MyMode == LBContents.regressiontest)
            {
                cbLoadPuzzlesAtStart.Visible = false;
                btnReset.Visible = true;
                btnReset.Text = "Close";
                tbSearchBox.Visible = false;

                btnAdd.Text = "Test All";

                btnOK.Text = "Test One";

                PuzzleInfo pi;
                string shown_name;
                string puzzle_name = "";
                List<string> Puzzles = NB.GetPuzzleNames();
                NBSettings oursettings = NB.GetSettings();
                if (Puzzles == null) return;
                bool wasfinished = false;
                int count = 0;
                foreach (string str in Puzzles)
                {
                    wasfinished = false;
                    pi = NB.GetPuzzleInfoFromName(str);
                    //shown_name = pi.PuzzleName;
                    shown_name = pi.NetTitle.GetText();
                    puzzle_name = pi.PuzzleName;
                    if (oursettings.CheckIfDone(str))
                    {
                        wasfinished = true;
                    }
                    List<string> tags = new List<string>(pi.PuzzleTags);
                    if(oursettings.HasReplay(puzzle_name)) tags.Add(TestString);
                    else tags.Add(NoTestString);
                    if (oursettings.HasPassed(puzzle_name)) tags.Add(PassedString);
                    if (oursettings.HasFailed(puzzle_name)) tags.Add(FailedString);
                    if (oursettings.HasPassed(puzzle_name)) tags.Add(PassedString);
                    if (!oursettings.HasFailed(puzzle_name) && !oursettings.HasPassed(puzzle_name) 
                        && oursettings.HasReplay(puzzle_name))
                        tags.Add(Untested);
                    foreach (string tag in tags)
                    {
                        if (isChecked(tag))
                        {
                            MyPuzzleEntry MPE = new MyPuzzleEntry();
                            MPE.PuzzleName = puzzle_name;
                            MPE.Title = shown_name;
                            MPE.isdone = wasfinished;
                            MPE.level = pi.strLevel;
                            MPE.InRegressionMode = true;
                            if (oursettings.HasPassed(puzzle_name)) MPE.PassedTest = true;
                            if (oursettings.HasFailed(puzzle_name)) MPE.FailedTest = true;
                            MPE.HasTest = oursettings.HasReplay(puzzle_name);
                            if (selected == "" && !wasfinished) selected = shown_name; //Select the first unfinished puzzle
                            lbWindowData.Items.Add(MPE);
                            if(MPE.HasTest) count++;  //we can only test-all if there are tests to do
                            break;
                        }
                    }
                }
                if (selected != null && selected != "")
                {
                    if (selectedIndex >= 0 && selectedIndex < lbWindowData.Items.Count)
                    {
                        lbWindowData.SelectedIndex = selectedIndex;
                        lbWindowData.TopIndex = topmost;
                    }
                }
                if (lbWindowData.SelectedIndex != -1)
                {
                    btnOK.Enabled = true;
                }
                else
                {
                    btnOK.Enabled = false;
                }
                if (count > 0) btnAdd.Enabled = true;
                else btnAdd.Enabled = false;
            }
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            NBSettings oursettings = NB.GetSettings();
            if (MyMode == LBContents.puzzles && lbWindowData.SelectedItem != null)
            {
                if (lbWindowData.SelectedItem is string)
                {
                    string TheName = lbWindowData.SelectedItem.ToString();
                    TheName = Regex.Replace(TheName, @"^\* ", "");
                    Visible = false;
                    BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"];
                    if (myWin == null)
                    {
                        myWin.Activate();
                    }
                    if (oursettings.AutoStartPuzzles != cbLoadPuzzlesAtStart.Checked)
                    {
                        oursettings.AutoStartPuzzles = cbLoadPuzzlesAtStart.Checked;
                        //                    oursettings.Save();
                    }
                    if (lbWindowData.SelectedItem != null)
                        NB.LoadNetworkFromResource(TheName);
                }
                else if (lbWindowData.SelectedItem is MyPuzzleEntry)
                {
                    MyPuzzleEntry MPE = (MyPuzzleEntry)lbWindowData.SelectedItem;
                    string TheName = MPE.PuzzleName;
                    Visible = false;
                    BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"];
                    if (myWin == null)
                    {
                        myWin.Activate();
                    }
                    if (oursettings.AutoStartPuzzles != cbLoadPuzzlesAtStart.Checked)
                    {
                        oursettings.AutoStartPuzzles = cbLoadPuzzlesAtStart.Checked;
                        //                    oursettings.Save();
                    }
                    if (lbWindowData.SelectedItem != null)
                        NB.LoadNetworkFromResource(TheName);
                }
                Close();
            }
            else if (MyMode == LBContents.regressiontest)
            {
                if (lbWindowData.SelectedItem is MyPuzzleEntry)
                {
                    MyPuzzleEntry MPE = (MyPuzzleEntry)lbWindowData.SelectedItem;
                    string TheName = MPE.PuzzleName;
                    //Visible = false;
                    BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"];
                    if (myWin != null)
                    {

                        if (oursettings.HasReplay(TheName))
                        {
                            //myWin.Activate();
                            FormColorForTesting();
                            myWin.replayNetwork(TheName, 1);
                            //Return back to the listbox window
                            Visible = true;
                            Activate();
                            FormColorBackToNormal();
                        }
                        else
                        {
                            if (lbWindowData.SelectedItem != null)
                            {
                                NB.LoadNetworkFromResource(TheName);
                            }
                        }
                    }
                    UpdateForm(); //If anything changed, show it
                }
            }
            else Close();
        }

        private void FormColorForTesting()
        {
            this.BackColor = Color.GreenYellow;
            Refresh();
        }
        private void FormColorBackToNormal()
        {
            this.BackColor = SystemColors.Control;

            Refresh();
        }
        private void FormColorContinuingLoop()
        {
            this.BackColor = Color.DarkGray;
            Refresh();
        }

        /// <summary>
        /// The checkmark was changed.  Tally up everything
        /// </summary>
        /// <param name="sender">The checkmark that changed</param>
        /// <param name="e"></param>
        private void genericCheckmarkChange(object sender, EventArgs e)
        {
            if (processing) return;
            CheckBox mybox = (CheckBox)sender;
            if (MyMode == LBContents.messages)
            {
                if (mybox.Checked)
                {
                    WhatToDisplay = WhatToDisplay | NB.ParseEnum<DebugLevel>(mybox.Text);
                }
                else
                {
                    WhatToDisplay = WhatToDisplay ^ NB.ParseEnum<DebugLevel>(mybox.Text);
                }
            }
            UpdateChecked();
        }

        private bool isChecked(string Name)
        {            
            foreach (Control mycontrol in panelCheckboxes.Controls)
            {
                //pull out the name
                CheckBox cb = (CheckBox)mycontrol;
                //make an enum.  See if that is set.  If so, mark it as checked
                if(cb.Text.ToLower() == Name.ToLower())
                {
                    return cb.Checked;
                }
            }
            return false;
        }

        private void UpdateChecked()
        {
            processing = true;
            DebugLevel toFind;
            int mycount = 0;
            string labelname = "";
            NBSettings oursettings = NB.GetSettings();
            if (MyMode == LBContents.puzzles)
            {
                foreach (Control mycontrol in panelCheckboxes.Controls)
                {
                    //pull out the name
                    CheckBox cb = (CheckBox)mycontrol;
                    //make an enum.  See if that is set.  If so, mark it as checked
                    if (cb.Checked)
                    {
                        mycount++;
                        labelname = mycontrol.Text;
                    }
                }
                if (mycount == 1)
                {
                    //We only have one item checked.  Store this value for later
                    oursettings.ProcessingLevel = labelname;
//                    oursettings.Save();
                }
            }
            if (MyMode == LBContents.messages)
            {
                foreach (Control mycontrol in panelCheckboxes.Controls)
                {
                    //pull out the name
                    CheckBox cb = (CheckBox)mycontrol;
                    //make an enum.  See if that is set.  If so, mark it as checked
                    toFind = NB.ParseEnum<DebugLevel>(mycontrol.Text);
                    if ((toFind & WhatToDisplay) == toFind)
                    {
                        cb.Checked = true;
                        labelname = mycontrol.Text;
                        mycount++;
                    }
                    else    //If not, mark it as not checked.
                    {
                        cb.Checked = false;
                    }
                }
            }
            processing=false;
            UpdateForm();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            NBSettings oursettings = NB.GetSettings();
            if (MyMode == LBContents.routes)
            {
                AddRoute();
            }
            //In puzzle mode, this is the cancel button
            if(MyMode == LBContents.puzzles)
            {
                if (oursettings.AutoStartPuzzles != cbLoadPuzzlesAtStart.Checked)
                {
                    oursettings.AutoStartPuzzles = cbLoadPuzzlesAtStart.Checked;
//                    oursettings.Save();
                }
                Close();
            }
            //In regression, this is the test all button
            if (MyMode == LBContents.regressiontest)
            {
                //Loop through all the visible puzzles & process them in-order.
                RegressionTestAll();
                UpdateForm();
            }
        }

        private void RegressionTestAll()
        {
            PuzzleInfo pi;
            List<string> Puzzles = NB.GetPuzzleNames();
            NBSettings oursettings = NB.GetSettings();
            if (Puzzles == null) return;
            List<string> NeedingToDo = new List<string>();
            foreach (string OnePuzzle in Puzzles)
            {
                pi = NB.GetPuzzleInfoFromName(OnePuzzle);
                //shown_name = pi.PuzzleName;
                List<string> tags = new List<string>(pi.PuzzleTags);
                if (oursettings.HasReplay(OnePuzzle)) tags.Add(TestString);
                else continue; //Do not try it if there is no replay
                if (oursettings.HasPassed(OnePuzzle)) continue; //No need to test it again if it passed
                if (oursettings.HasFailed(OnePuzzle)) tags.Add(FailedString);
                if (!oursettings.HasFailed(OnePuzzle) && !oursettings.HasPassed(OnePuzzle)
                    && oursettings.HasReplay(OnePuzzle))
                    tags.Add(Untested);
                foreach (string tag in tags)
                {
                    if (isChecked(tag))
                    {
                        NeedingToDo.Add(OnePuzzle);
                        break;
                    }
                }
            }

            //Now, loop through and do them
            int count = NeedingToDo.Count;
            foreach(string OnePuzzle in NeedingToDo)
            {
                //Visible = false;
                BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"];
                if (myWin != null)
                {
                    //myWin.Activate();
                    FormColorForTesting();
                    myWin.replayNetwork(OnePuzzle, 1, count--);
                    //Return back to the listbox window
                    Visible = true;
                    Activate();
                    FormColorContinuingLoop();
                }
            }

            FormColorBackToNormal();
        }


        private void AddRoute()
        {
            NB_IPAddress newip = new NB_IPAddress(NB.ZeroIPString, NB.ZeroIPString, NB.ZeroIPString);
            newip.Edit(myNetDevice, this, NB.Translate("LBW_AddRouteCreate"));
            if (!newip.Equals(new NB_IPAddress(NB.ZeroIPString, NB.ZeroIPString, NB.ZeroIPString)))
            {
                myNetDevice.AddRoute(newip);
            }
            UpdateForm();
        }

        private void lbWindowData_DoubleClick(object sender, EventArgs e)
        {
            
            if (MyMode == LBContents.routes)
            {
                if (lbWindowData.SelectedIndex >= EditableCount) return;
                if (lbWindowData.SelectedIndex < 1) return;
                //we always subtract 1 since we have added one line of comment to the list
                myNetDevice.EditRoute(lbWindowData.SelectedIndex - 1, this);
            }
            if(MyMode == LBContents.dhcp)
            {
                //We always add one since we are skipping the loopback device
                myNetDevice.EditDHCP(lbWindowData.SelectedIndex + 1, this);
            }
            if (MyMode == LBContents.puzzles || MyMode == LBContents.regressiontest)
            {
                //Just like pressing the OK button.   We load the map / process regression
                btnOK_Click(sender, e);
            }
            UpdateForm();
        }
        private void lbWindowData_Edit_Click(object sender, EventArgs e)
        {
            lbWindowData_DoubleClick(sender, e);
        }
        private void lbWindowData_Delete_Click(object sender, EventArgs e)
        {
            if (MyMode == LBContents.routes)
            {
                if (lbWindowData.SelectedIndex >= EditableCount) return;
                if (lbWindowData.SelectedIndex < 1) return;
                //we always subtract 1 since we have added one line of comment to the list
                myNetDevice.DeleteRoute(lbWindowData.SelectedIndex - 1);
            }
            UpdateForm();
        }
        private void lbWindowData_RightMouseUp(object sender, MouseEventArgs e)
        {
            int index=0;
            if(MyMode == LBContents.routes)
            {
                if (lbWindowData.ContextMenuStrip == null)
                {
                    lbWindowData.ContextMenuStrip = new ContextMenuStrip();
                }
                lbWindowData.ContextMenuStrip.Items.Clear();
                lbWindowData.ContextMenuStrip.Items.Add(NB.Translate("_Edit"));
                lbWindowData.ContextMenuStrip.Items[index++].Click += lbWindowData_Edit_Click;
                lbWindowData.ContextMenuStrip.Items.Add(NB.Translate("_Delete"));
                lbWindowData.ContextMenuStrip.Items[index++].Click += lbWindowData_Delete_Click;
            }
        }
        private void lbWindowData_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                lbWindowData_RightMouseUp(sender, e);
                return;
            }
            else
            {
                if(MyMode == LBContents.puzzles)
                {
                    if ((Form.ModifierKeys & Keys.Control) == Keys.Control && (Form.ModifierKeys & Keys.Alt) == Keys.Alt)
                    {
                        //We are control + alt clicking on something
                        if (lbWindowData.SelectedItem != null)
                        {
                            string TheName = lbWindowData.SelectedItem.ToString();
                            TheName = Regex.Replace(TheName, @"^\* ", "");
                            //If the puzzle is solved, mark it as unsolved.
                            //If it is unsolved, mark it as solved.
                            NBSettings oursettings = NB.GetSettings();
                            if(oursettings != null)
                            {
                                if (oursettings.ScoreList.Contains(TheName))
                                {
                                    oursettings.ScoreList.Remove(TheName);
                                }
                                else
                                    oursettings.ScoreList.Add(TheName);
                            }
                        }
                    }
                    UpdateForm();
                }
                if (MyMode == LBContents.regressiontest)
                    UpdateForm();
            }
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            if (MyMode == LBContents.regressiontest)
            {
                //In regressiontest mode, this is the cancel.
                ClosingRegression = true;
                Close();
                return;
            }
            else
            {
                DialogResult answer = MessageBox.Show(NB.Translate("LBW_btnResetYouSure"), NB.Translate("LBW_btnResetForget"), MessageBoxButtons.YesNo);
                if (answer == System.Windows.Forms.DialogResult.Yes)
                {
                    NBSettings oursettings = NB.GetSettings();
                    oursettings.ScoreList.Clear();
                    UpdateForm();
                }
            }
        }

        private void tbSearchBox_TextChanged(object sender, EventArgs e)
        {
            //If there are more than 2 characters, then we start to see if we can filter it
            if (tbSearchBox.Text.Length > 2)
            {
                //Now we filter the results
                FilterString = tbSearchBox.Text;
                UpdateForm();
            }
            else
            {
                FilterString = "";
                UpdateForm();
            }
        }
    }
}
