/// <summary>
 /// Note: routesToAltn can be empty. In that case, alternates are not used.
 /// </summary>
 public FuelReportGenerator(
     AirportManager airportList,
     ICrzAltProvider altProvider,
     IWxTableCollection windTable,
     Route routeToDest,
     IEnumerable <Route> routesToAltn,
     FuelParameters para,
     double maxAlt = 41000.0)
 {
     this.airportList  = airportList;
     this.altProvider  = altProvider;
     this.windTable    = windTable;
     this.routeToDest  = routeToDest;
     this.routesToAltn = routesToAltn.ToList();
     this.para         = para;
     this.maxAlt       = maxAlt;
 }
        private void Calculate(object sender, EventArgs e)
        {
            fuelReportTxtBox.ForeColor = Color.Black;
            fuelReportTxtBox.Text      = "";

            var            validator = new FuelParameterValidator(this);
            FuelParameters para      = null;

            try
            {
                para = validator.Validate();
            }
            catch (InvalidUserInputException ex)
            {
                this.ShowWarning(ex.Message);
                return;
            }

            var altnRoutes = AltnControl.Routes;

            if (altnRoutes.Any(r => r == null))
            {
                this.ShowWarning("All alternate routes must be entered.");
                return;
            }

            if (RouteToDest == null)
            {
                this.ShowWarning("Route to destination must be entered.");
                return;
            }

            var windTables = windTableLocator.Instance;

            if (windTables is DefaultWindTableCollection)
            {
                var result = this.ShowDialog(
                    "The wind data has not been downloaded. " +
                    "Continue to calculate and ignore wind aloft?",
                    MsgBoxIcon.Info,
                    "",
                    DefaultButton.Button1,
                    "Yes", "No", "Cancel");

                if (result != MsgBoxResult.Button1)
                {
                    return;
                }
            }

            FuelReport fuelReport = null;

            try
            {
                fuelReport = new FuelReportGenerator(
                    airportList,
                    new BasicCrzAltProvider(),
                    windTables,
                    RouteToDest.Expanded,
                    altnRoutes,
                    para).Generate();
            }
            catch (InvalidPlanAltitudeException)
            {
                this.ShowWarning("Cannot find a valid cruising altitude.");
                return;
            }

            var ac = GetCurrentAircraft().Config;

            if (fuelReport.TotalFuel > ac.MaxFuelKg)
            {
                var msg = InsufficientFuelMsg(fuelReport.TotalFuel, ac.MaxFuelKg, WeightUnit);
                this.ShowInfo(msg, "Insufficient fuel");
                return;
            }

            string outputText = fuelReport.ToString(WeightUnit);

            fuelReportTxtBox.Text = "\n" + outputText.ShiftToRight(20);

            AircraftRequest = new AircraftRequest(
                acListComboBox.Text,
                registrationComboBox.Text,
                para.Zfw + fuelReport.TakeoffFuel,
                para.Zfw + fuelReport.PredictedLdgFuel,
                para.Zfw,
                WeightUnit);

            AircraftRequestChanged?.Invoke(this, EventArgs.Empty);
            SaveStateToFile();
            ScrollToBottom();
        }