/// <summary>
        /// Constructor for the Train GUI.
        /// </summary>
        /// <param name="environment">The environment being used by the entire simulation.</param>
        public TrainGUI(ISimulationEnvironment environment)
        {
            InitializeComponent();

            _dropDownOpen = false;
            _GUIPaused = false;

            allTrainComboBox.SelectedIndexChanged += allTrainComboBox_SelectedIndexChanged;
            _allTrains = environment.AllTrains;
            _numTrains = _allTrains.Count;

            _timer = 0;

            PopulateComboBox(_allTrains);

            if (_allTrains != null && _allTrains.Count > 0)
            {
                _selectedTrain = (Train)_allTrains[0];
                allTrainComboBox.SelectedItem = _selectedTrain;
            }

            UpdateGUI();

            _environment = environment;
            _environment.Tick += _environment_Tick;
        }
        /// <summary>
        ///     Toggles signal pickup failure.
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">Event args</param>
        private void buttonSignalPickupFailure_Click(object sender, EventArgs e)
        {
            _selectedTrain = (Train)allTrainComboBox.SelectedItem;

            if (_selectedTrain != null)
            {
                if (_selectedTrain.SignalPickupFailure)
                {
                    _selectedTrain.SignalPickupFailure = false;
                    UpdateGUI();
                }
                else
                {
                    _selectedTrain.SignalPickupFailure = true;
                    UpdateGUI();
                    DisplayError("CRITICAL ERROR: Signal pickup failure for " + _selectedTrain.ToString());
                }
            }
        }
        /// <summary>
        ///     Applies emergency brake.
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">Event args</param>
        private void buttonEmergencyBrake_Click(object sender, EventArgs e)
        {
            _selectedTrain = (Train)allTrainComboBox.SelectedItem;

            if (_selectedTrain != null)
            {
                _selectedTrain.EmergencyBrake();
                UpdateGUI();
            }
        }
        private static Form GuiTestFramework(int test)
        {
            ////////////////////////////////////////////////////////////////////////////////////////
            //                              Initializations                                       //
            ////////////////////////////////////////////////////////////////////////////////////////

            // Environment object
            var environment = new SimulationEnvironment.SimulationEnvironment();

            IBlock b0 = new TrackModel.Block(1, StateEnum.Healthy, 0, 0, 0, new[] {0, 0}, 10, DirEnum.East, new[] {""}, 0, 0, 0, "Red",70);
            IBlock b1 = new TrackModel.Block(2, StateEnum.Healthy, 1, 0, 0, new[] {1, 1}, 10, DirEnum.East, new[] {""}, 0, 0, 0, "Red",70);
            IBlock b2 = new TrackModel.Block(3, StateEnum.Healthy, 2, 0, 0, new[] {2, 2}, 10, DirEnum.East, new[] {""}, 0, 0, 0, "Red",70);
            IBlock b3 = new TrackModel.Block(4, StateEnum.BrokenTrackFailure, 3, 0, 0, new[] {3, 3}, 10, DirEnum.East, new[] {""}, 0, 0, 0, "Red",70);

            var sectionA = new List<IBlock> {b0};
            var sectionB = new List<IBlock> {b1, b2};
            var sectionC = new List<IBlock> {b3};

            // Previous track controller's circuit
            var prevCircuit = new TrackCircuit(environment, sectionA);
            // Our track circuit
            var currCircuit = new TrackCircuit(environment, sectionB);
            // Next track controller's circuit
            var nextCircuit = new TrackCircuit(environment, sectionC);

            var prev = new TrackController.TrackController(environment, prevCircuit);
            var curr = new TrackController.TrackController(environment, currCircuit);
            var next = new TrackController.TrackController(environment, nextCircuit);

            //Create TrackModel
            var trackMod = new TrackModel.TrackModel(environment);
            //Let TrackModel read in the lines before you proceed..shouldnt be done this way, but needed to stop CTC Office from faulting
            bool res = trackMod.provideInputFile("red.csv");
            //Console.WriteLine("Res was "+res);
            res = trackMod.provideInputFile("green.csv");
            //Console.WriteLine("Res was " + res);

            environment.TrackModel = trackMod;
            prev.Previous = null;
            prev.Next = curr;

            curr.Previous = prev;
            curr.Next = next;

            next.Previous = curr;
            next.Next = null;

            // Assign the same track controller to both lines
            var office = new CTCOffice.CTCOffice(environment, prev, prev);

            environment.CTCOffice = office;
            environment.PrimaryTrackControllerGreen = prev;
            environment.PrimaryTrackControllerRed = prev;

            ////////////////////////////////////////////////////////////////////////////////////////
            //                            End Initializations                                     //
            ////////////////////////////////////////////////////////////////////////////////////////

            var form = new Form();
            var control = new UserControl();
            switch (test)
            {
                case 0: // SystemScheduler

                    var testSystemScheduler = new SystemScheduler.SystemScheduler(environment, office);
                    control = new SystemSchedulerGUI(environment, testSystemScheduler, office);
                    environment.StartTick();
                    break;
                case 1: // CTCOffice
                    environment = null;

                    b0 = null;
                    b1 = null;
                    b2 = null;
                    b3 = null;

                    sectionA = null;
                    sectionB = null;
                    sectionC = null;

                    prevCircuit = null;
                    currCircuit = null;
                    nextCircuit = null;

                    prev = null;
                    curr = null;
                    next = null;

                    trackMod = null;
                    office = null;

                    new CTCGUITest();
                    break;
                case 2: // TrackModel
                    control = new TrackModelGUI(environment, trackMod);
                    break;
                case 3: // TrackController
                    ITrainModel t = new Train(0, b0, environment);

                    environment.AllTrains.Add(t);

                    prevCircuit.Trains.Add(0, t);

                    control = new TrackControllerUi(environment, environment.PrimaryTrackControllerRed);
                    break;
                case 4: // TrainModel
                    var loc = new int[2];
                    loc[0] = 10;
                    loc[1] = 10;
                    var start = new Block(0, StateEnum.Healthy, 0, 0, -0.02, loc, 100, DirEnum.East, null, 1, 2, 0, "Red",70);
                    environment.AddTrain(new Train(0, start, environment));
                    environment.AddTrain(new Train(1, start, environment));

                    var train0 = (Train)environment.AllTrains[0];
                    train0.ChangeMovement(200);

                    control = new TrainGUI(environment);

                    break;
                case 5: // TrainController
                    var loc2 = new int[2];
                    loc2[0] = 10;
                    loc2[1] = 10;
                    var start2 = new Block(0, StateEnum.Healthy, 0, 0, 0, loc2, 100, DirEnum.East, null, 1, 2, 0, "Red",70);
                    var tc = new TrainController.TrainController(environment, new Train(0, start2, environment));
                    control = new TrainControllerUI(tc, environment);
                    break;
            }

            if (environment != null)
            {
                environment.StartTick();
            }

            if (form != null)
            {
                form.Controls.Add(control);
                form.AutoSize = true;
            }
            else
            {
                return null;
            }

            return form;
        }
        private bool TestTemperature(List<string> messages)
        {
            Train train = new Train(0, startBlock, _environment);
            train.Temperature = 70;

            if (train.Temperature != 70) // error
            {
                string error = train.ToString() + " did not set temperature correctly.";
                messages.Add(error);
                return false;
            }

            return true;
        }
        private bool TestRemovePassengers(List<string> messages)
        {
            bool result = true;

            Train train = new Train(0, startBlock, _environment);
            train.NumPassengers = 25;
            train.NumCrew = 10;

            // remove passengers
            train.NumPassengers = 10;
            train.NumCrew = 0;

            if ((train.NumPassengers != 10) || (train.NumCrew != 0)) // error
            {
                string error = train.ToString() + " did not remove";
                if (train.NumPassengers == -25)
                    error += " passengers,";
                if (train.NumCrew == -10)
                    error += " crew";

                error += " correctly.";
                messages.Add(error);
                result = false;
            }

            // reset
            train.NumPassengers = 0;
            train.NumCrew = 0;

            return result;
        }
        private bool TestMovement_PositiveGrade(List<string> messages)
        {
            bool result = true;

            Block oldStart = startBlock;
            startBlock = new Block(0, StateEnum.Healthy, 0, 0, 0.01, new[] { 0, 0 }, 100000, DirEnum.East, new[] { "" }, 0, 0, 0, "Red", 70);
            blocks[0] = startBlock;
            Train train = new Train(0, startBlock, _environment);

            train.ChangeMovement(200);
            train.updateMovement(); // should be less than 0.5

            if (train.CurrentAcceleration >= 0.5) // error
            {
                string error = train.ToString() + " did not lose any acceleration due to slope.";
                messages.Add(error);
                result = false;
            }

            // reset
            blocks[0] = oldStart;
            startBlock = oldStart;

            return result;
        }
        private bool TestBrakeFailureMovement(List<string> messages)
        {
            bool result = true;

            Train train = new Train(0, startBlock, _environment);
            train.BrakeFailure = true;
            if (train.ChangeMovement(-200)) // error, braked during brake failure
            {
                string error = train.ToString() + " applied brakes during brake failure.";
                messages.Add(error);
                result = false;
            }

            if (!train.ChangeMovement(200)) // error, unable to supply power during brake failure
            {
                string error = train.ToString() + " was not able to accelerate during brake failure.";
                messages.Add(error);
                result = false;
            }

            train.BrakeFailure = false; // reset

            return result;
        }
        private bool TestMovement_NegativeGrade(List<string> messages)
        {
            bool result = true;

            Block oldStart = startBlock;
            startBlock = new Block(0, StateEnum.Healthy, 0, 0, -0.01, new[] { 0, 0 }, 100000, DirEnum.East, new[] { "" }, 0, 0, 0, "Red", 70);
            blocks[0] = startBlock;
            Train train = new Train(1, startBlock, _environment);

            train.ChangeMovement(200);

            // allow 10 iterations of update movement
            for (int i = 0; i < 8; i++)
            {
                train.updateMovement();
            }

            train.EmergencyBrake();
            train.updateMovement(); // should be greater than -2.73

            if (train.CurrentAcceleration == -2.73) // error
            {
                string error = train.ToString() + " did not gain any acceleration due to slope.";
                messages.Add(error);
                result = false;
            }

            // reset
            blocks[0] = oldStart;
            startBlock = oldStart;

            return result;
        }
        private bool TestMass(List<string> messages)
        {
            bool result = true;

            double initialTrainMass = 40900; //kilograms
            double personMass = 90; //kilograms
            Random random = new Random();

            Train train = new Train(0, startBlock, _environment);

            int randomNum = random.Next(0, 223); // 0 to 222 passengers
            train.NumPassengers = randomNum;

            double compareMass = initialTrainMass + personMass * randomNum;

            if (compareMass != train.TotalMass) // error
            {
                string error = train.ToString() + " did not calculate mass correctly.";
                messages.Add(error);
                result = false;
            }

            train.NumPassengers = 0; // reset

            return result; // all passed
        }
        private bool TestLights(List<string> messages)
        {
            Train train = new Train(0, startBlock, _environment);
            train.LightsOn = true;

            if (train.LightsOn == false) // error
            {
                string error = train.ToString() + " did not turn the lights on correctly.";
                messages.Add(error);
                return false;
            }

            train.LightsOn = false;

            if (train.LightsOn == true) // error
            {
                string error = train.ToString() + " did not turn the lights off correctly.";
                messages.Add(error);
                return false;
            }

            return true;
        }
        private bool TestEngineFailureMovement(List<string> messages)
        {
            bool result = true;

            Train train = new Train(0, startBlock, _environment);
            train.EngineFailure = true;
            if (train.ChangeMovement(200)) // error, changed movement during engine failure
            {
                string error = train.ToString() + " applied power during engine failure.";
                messages.Add(error);
                result = false;
            }

            if (train.ChangeMovement(-200)) // error, able to brake during engine failure
            {
                string error = train.ToString() + " applied brake during engine failure.";
                messages.Add(error);
                result = false;
            }

            train.EngineFailure = false; // reset

            return result;
        }
        private bool TestEmergencyBrake(List<string> messages)
        {
            Train train = new Train(0, startBlock, _environment);

            train.ChangeMovement(200);

            // allow 10 iterations of update movement
            for (int i = 0; i < 10; i++)
            {
                train.updateMovement();
            }

            train.EmergencyBrake();
            train.updateMovement();

            if (train.CurrentAcceleration != -2.73) // error
            {
                string error = train.ToString() + " emergency brake did not set maximum deceleration correctly.";
                messages.Add(error);
                return false;
            }
            return true;
        }
        private bool TestDoors(List<string> messages)
        {
            Train train = new Train(0, startBlock, _environment);
            train.DoorsOpen = true;

            if (train.DoorsOpen == false) // error
            {
                string error = train.ToString() + " did not open doors correctly.";
                messages.Add(error);
                return false;
            }

            train.DoorsOpen = false;

            if (train.DoorsOpen == true) // error
            {
                string error = train.ToString() + " did not close doors correctly.";
                messages.Add(error);
                return false;
            }

            return true;
        }
        private bool TestMovement_NoGrade(List<string> messages)
        {
            Train train = new Train(0, startBlock, _environment);

            train.ChangeMovement(200); // defaults to 0.5 because of zero grade
            train.updateMovement();

            if (train.CurrentAcceleration != 0.5) // error
            {
                string error = train.ToString() + " acceleration did not default to 0.5.";
                messages.Add(error);
                return false;
            }
            return true;
        }
 /// <summary>
 ///     Detects when the selected index of the combo box changes, and updates the GUI.
 /// </summary>
 /// <param name="sender">Sender</param>
 /// <param name="e">Event args</param>
 private void allTrainComboBox_SelectedIndexChanged(object sender, EventArgs e)
 {
     _selectedTrain = (Train)allTrainComboBox.SelectedItem;
     UpdateGUI();
 }
        private bool TestAddPassengers(List<string> messages)
        {
            bool result = true;

            Train train = new Train(0, startBlock, _environment);

            // correct add passengers
            train.NumPassengers = 25;
            train.NumCrew = 10;

            if ((train.NumPassengers != 25) || (train.NumCrew != 10)) // error
            {
                string error = train.ToString() + " did not add";
                if (train.NumPassengers != 25)
                    error += " passengers,";
                if (train.NumCrew != 10)
                    error += " crew";

                error += " correctly.";
                messages.Add(error);
                result = false;
            }

            // incorrect negative add passengers
            train.NumPassengers = -25;
            train.NumCrew = -10;

            if ((train.NumPassengers != 25) || (train.NumCrew != 10)) // error
            {
                string error = train.ToString() + " set";
                if (train.NumPassengers == -25)
                    error += " passengers,";
                if (train.NumCrew == -10)
                    error += " crew";

                error += " to negative number.";
                messages.Add(error);
                result = false;
            }

            // incorrect too many passengers
            train.NumPassengers = 500;
            train.NumCrew = 400;

            if ((train.NumPassengers != 25) || (train.NumCrew != 10)) // error
            {
                string error = train.ToString() + " set";
                if (train.NumPassengers == -25)
                    error += " passengers,";
                if (train.NumCrew == -10)
                    error += " crew";

                error += " over maximum capacity.";
                messages.Add(error);
                result = false;
            }

            // reset
            train.NumPassengers = 0;
            train.NumCrew = 0;

            return result;
        }