/// <summary>
        /// Searches for a mapping immatriculation to member number set and if found a match, it sets the mapped MemberNumber.
        /// </summary>
        /// <param name="proffixData"></param>
        /// <returns>true, if find a matching immatriculation, otherwise false</returns>
        public bool FindImmatriculationAndMapMemberNumber(ProffixData proffixData)
        {
            foreach (var immatriculation in _memberNrRemapping.Keys)
            {
                if (immatriculation.Trim().ToUpper() == proffixData.FlightBoxData.Immatriculation.Trim().ToUpper())
                {
                    proffixData.MemberNumber = _memberNrRemapping[immatriculation];
                    return(true);
                }
            }

            return(false);
        }
        public bool FindLastnameAndSetMemberNumber(ProffixData proffixData)
        {
            foreach (var lastname in _memberList.Keys)
            {
                if (lastname.Trim().ToLower() == proffixData.FlightBoxData.Lastname.Trim().ToLower())
                {
                    proffixData.MemberNumber = _memberList[lastname];
                    return(true);
                }
            }

            return(false);
        }
        public bool IsNoLdgTaxMember(ProffixData proffixData)
        {
            if (string.IsNullOrWhiteSpace(proffixData.MemberNumber.Trim()))
            {
                return(false);
            }

            if (_noLdgTaxMembers.Exists(x => x.Contains(proffixData.MemberNumber.Trim())))
            {
                return(true);
            }

            return(false);
        }
        public bool FindMemberNumberInProffix(ProffixData proffixData)
        {
            if (Settings.Default.ReadProffixDbData == false)
            {
                return(true);
            }

            if (_proffixAddressNumbers.Contains(proffixData.MemberNumber.Trim().ToUpper()))
            {
                return(true);
            }

            proffixData.MemberNumberInProffixNotFound = true;
            return(false);
        }
        public void Convert()
        {
            try
            {
                ExportErrorMessage = string.Empty;
                HasExportError     = false;

                //loading proffix address numbers from database
                var nrOfAddressesFromProffixRead = _dataManager.ReadProffixDatabase();

                if (ImportFileName.ToLower().EndsWith(".csv") == false)
                {
                    var directory = new DirectoryInfo(ImportFileName);
                    var lastFile  = directory.GetFiles().OrderByDescending(f => f.LastWriteTime).FirstOrDefault();

                    if (lastFile == null)
                    {
                        OnLogEventRaised("Konnte keine aktuelle Datei zum Importieren finden!");
                        throw new ApplicationException($"Konnte keine aktuelle Datei zum Importieren in Verzeichnis {ImportFileName} finden!");
                    }

                    ImportFileName = lastFile.FullName;
                    OnLogEventRaised($"Verwende Datei: {ImportFileName}");
                }

                _logEntries = new List <string>();
                var flightBoxDataList = ReadFile();
                var proffixDataList   = new List <ProffixData>();
                CreationTimeStamp = DateTime.Now;

                OnLogEventRaised("Bereinige Basis-Daten...");

                if (Settings.Default.ReadProffixDbData)
                {
                    OnLogEventRaised($"Mitgliedernummern werden anhand der Proffix-Datenbank überprüft. {nrOfAddressesFromProffixRead} Adressen aus Proffix geladen.");
                }
                else
                {
                    OnLogEventRaised("Proffix-Datenbank wird für die Mitgliedernummer-Prüfung nicht verwendet!");
                }

                foreach (var flightBoxData in flightBoxDataList)
                {
                    var proffixData = new ProffixData(flightBoxData);

                    //check movement date within the valid import range
                    //we won't import old movement data into proffix
                    var minMovementDate = new DateTime(DateTime.Now.AddMonths(-1).Year, DateTime.Now.AddMonths(-1).Month, 1);

                    if (flightBoxData.MovementDateTime < minMovementDate)
                    {
                        // found movement older than the previous months
                        flightBoxData.IsOlderMovementDate = true;
                        OnLogEventRaised(
                            $"Alte Flugbewegung gefunden vom {flightBoxData.MovementDateTime.ToShortDateString()} (Zeile: {flightBoxData.LineNumber}).");

                        if (_ignoreDateRange == false)
                        {
                            ExportErrorMessage = "Alte Flugbewegung wurde gefunden und Warnung bei alten Daten darf nicht ignoriert werden. Verarbeitung wird abgebrochen.";
                            HasExportError     = true;
                            WriteLogFile();
                            ExportFinished?.Invoke(this, EventArgs.Empty);
                            return;
                        }
                    }

                    // try to find MemberNumber based on name if no MemberNumber is set
                    if (string.IsNullOrWhiteSpace(flightBoxData.MemberNumber) || flightBoxData.MemberNumber == "000000")
                    {
                        if (_dataManager.FindLastnameAndSetMemberNumber(proffixData))
                        {
                            OnLogEventRaised(
                                $"MemberNumber {proffixData.MemberNumber} für {flightBoxData.Lastname} mit {flightBoxData.Immatriculation} gesetzt (Zeile: {flightBoxData.LineNumber}).");
                        }
                    }

                    // set MemberNumber based on immatriculation
                    if (_dataManager.FindImmatriculationAndMapMemberNumber(proffixData))
                    {
                        OnLogEventRaised($"Setze spezielle Mitgliedernummer für {proffixData.FlightBoxData.Immatriculation} (Zeile: {flightBoxData.LineNumber}): Alte Mitgliedernummer {proffixData.FlightBoxData.MemberNumber}, neue Mitgliedernummer {proffixData.MemberNumber}");
                    }

                    if (Settings.Default.ReadProffixDbData && _dataManager.FindMemberNumberInProffix(proffixData) == false)
                    {
                        OnLogEventRaised($"Mitgliedernummer {proffixData.MemberNumber} für {proffixData.FlightBoxData.Lastname} mit {proffixData.FlightBoxData.Immatriculation} in Proffix-Datenbank nicht gefunden (Zeile: {flightBoxData.LineNumber})");
                    }

                    proffixDataList.Add(proffixData);
                }

                Thread.Sleep(50);

                WriteBaseFile(proffixDataList);

                Thread.Sleep(50);

                foreach (var proffixData in proffixDataList)
                {
                    if (_dataManager.IsNoLdgTaxMember(proffixData))
                    {
                        proffixData.FlightBoxData.IgnoreLandingTax = true;
                    }

                    if (proffixData.MemberNumber == "999605" &&
                        proffixData.FlightBoxData.TypeOfTraffic == (int)TypeOfTraffic.Instruction)
                    {
                        // Heli Sitterdorf is always private tax not training
                        proffixData.FlightBoxData.TypeOfTraffic = (int)TypeOfTraffic.Private;
                    }

                    if ((proffixData.MemberNumber == "999998" || proffixData.MemberNumber == "383909") &&
                        proffixData.FlightBoxData.TypeOfTraffic == (int)TypeOfTraffic.Instruction)
                    {
                        // Stoffel Aviation is external on instruction
                        proffixData.FlightBoxData.IsHomebased = false;
                    }

                    //TODO: Handle maintenance flights from Seiferle

                    // filtering for tow flights and departure movements are handled within the FlightBoxData class directly

                    if (string.IsNullOrWhiteSpace(proffixData.MemberNumber) || proffixData.MemberNumber == "000000")
                    {
                        proffixData.MemberNumberInProffixNotFound = true;

                        ExportErrorMessage +=
                            $"{Environment.NewLine}Fehlerhafte MemberNumber {proffixData.MemberNumber} für {proffixData.FlightBoxData.Lastname} mit {proffixData.FlightBoxData.Immatriculation} gefunden (Zeile: {proffixData.FlightBoxData.LineNumber}).";
                        OnLogEventRaised(
                            $"Fehlerhafte MemberNumber {proffixData.MemberNumber} für {proffixData.FlightBoxData.Lastname} mit {proffixData.FlightBoxData.Immatriculation} gefunden (Zeile: {proffixData.FlightBoxData.LineNumber}).");
                    }

                    CalculateLandingTax(proffixData);
                }

                if (HasExportError)
                {
                    WriteLogFile();
                    ExportFinished?.Invoke(this, EventArgs.Empty);
                    return;
                }

                Thread.Sleep(50);
                OnLogEventRaised(string.Empty);
                var folder         = Path.Combine(ExportFolderName, CreationTimeStamp.ToString("yyyy-MM-dd"));
                var exportFilename = Path.Combine(folder, $"{CreationTimeStamp.ToString("yyyy-MM-dd-HHmm")}_LdgTaxes_without_Remarks (to Import in Proffix).csv");
                var listToExport   = proffixDataList.Where(x => x.FlightBoxData.IsDepartureMovement == false &&
                                                           x.FlightBoxData.IsMaintenanceFlight == false &&
                                                           x.FlightBoxData.IsTowFlight == false &&
                                                           x.FlightBoxData.IgnoreLandingTax == false &&
                                                           string.IsNullOrWhiteSpace(x.FlightBoxData.Remarks) &&
                                                           x.MemberNumberInProffixNotFound == false)
                                     .ToList();

                if (listToExport.Any())
                {
                    OnLogEventRaised($"Exportiere Proffix-Daten ohne Bemerkungen in Datei: {exportFilename}");
                    var exporter = new ProffixDataCsvExporter(exportFilename, listToExport);
                    exporter.Export();
                    OnLogEventRaised(
                        $"{exporter.NumberOfLinesExported} Proffix-Daten ohne Bemerkungen erfolgreich exportiert.");
                }
                else
                {
                    OnLogEventRaised(
                        $"Keine Proffix-Daten ohne Bemerkungen exportiert. Datei: {exportFilename} wurde nicht erzeugt!");
                }

                Thread.Sleep(50);
                OnLogEventRaised(string.Empty);

                exportFilename = Path.Combine(folder, $"{CreationTimeStamp.ToString("yyyy-MM-dd-HHmm")}_LdgTaxes_With_MemberNumberNotFound_Error (to correct and Import in Proffix).csv");
                listToExport   = proffixDataList.Where(x => x.FlightBoxData.IsDepartureMovement == false &&
                                                       x.FlightBoxData.IsMaintenanceFlight == false &&
                                                       x.FlightBoxData.IsTowFlight == false &&
                                                       x.FlightBoxData.IgnoreLandingTax == false &&
                                                       x.MemberNumberInProffixNotFound)
                                 .ToList();

                if (listToExport.Any())
                {
                    OnLogEventRaised($"Exportiere Proffix-Daten mit fehlerhaften Mitgliedernummern in Datei: {exportFilename}");
                    var exporter = new ProffixDataCsvExporter(exportFilename, listToExport);
                    exporter.Export();
                    OnLogEventRaised(
                        $"{exporter.NumberOfLinesExported} Proffix-Daten mit fehlerhaften Mitgliedernummern erfolgreich exportiert.");
                }
                else
                {
                    OnLogEventRaised(
                        $"Keine Proffix-Daten mit fehlerhaften Mitgliedernummern exportiert. Datei: {exportFilename} wurde nicht erzeugt!");
                }

                Thread.Sleep(50);
                OnLogEventRaised(string.Empty);

                exportFilename = Path.Combine(folder, $"{CreationTimeStamp.ToString("yyyy-MM-dd-HHmm")}_LdgTaxes_with_Remarks (to check and import in Proffix).csv");
                listToExport   = proffixDataList.Where(x => x.FlightBoxData.IsDepartureMovement == false &&
                                                       x.FlightBoxData.IsMaintenanceFlight == false &&
                                                       x.FlightBoxData.IsTowFlight == false &&
                                                       x.FlightBoxData.IgnoreLandingTax == false &&
                                                       string.IsNullOrWhiteSpace(x.FlightBoxData.Remarks) == false &&
                                                       x.MemberNumberInProffixNotFound == false)
                                 .ToList();

                if (listToExport.Any())
                {
                    OnLogEventRaised(
                        $"Exportiere Daten mit Bemerkungen zur Prüfung und Importieren in Proffix in Datei: {exportFilename}");
                    var exporter = new ProffixDataCsvExporter(exportFilename, listToExport);
                    exporter.Export();
                    OnLogEventRaised(
                        $"{exporter.NumberOfLinesExported} Daten mit Bemerkungen zur Prüfung und Importieren in Proffix erfolgreich exportiert.");
                }
                else
                {
                    OnLogEventRaised(
                        $"Keine Daten mit Bemerkungen zur Prüfung und Importieren in Proffix exportiert. Datei: {exportFilename} wurde nicht erzeugt!");
                }

                Thread.Sleep(50);
                OnLogEventRaised(string.Empty);

                exportFilename = Path.Combine(folder, $"{CreationTimeStamp.ToString("yyyy-MM-dd-HHmm")}_No_LdgTaxes_without_Remarks (not to import).csv");
                listToExport   = proffixDataList.Where(x => (x.FlightBoxData.IsMaintenanceFlight ||
                                                             x.FlightBoxData.IsTowFlight ||
                                                             x.FlightBoxData.IgnoreLandingTax) &&
                                                       string.IsNullOrWhiteSpace(x.FlightBoxData.Remarks))
                                 .ToList();

                if (listToExport.Any())
                {
                    OnLogEventRaised($"Exportiere Nicht-Proffix-Daten ohne Bemerkungen in Datei: {exportFilename}");
                    var exporter = new ProffixDataCsvExporter(exportFilename, listToExport);
                    exporter.Export();
                    OnLogEventRaised(
                        $"{exporter.NumberOfLinesExported} Nicht-Proffix-Daten ohne Bemerkungen erfolgreich exportiert.");
                }
                else
                {
                    OnLogEventRaised(
                        $"Keine Nicht-Proffix-Daten ohne Bemerkungen exportiert. Datei: {exportFilename} wurde nicht erzeugt!");
                }

                Thread.Sleep(50);
                OnLogEventRaised(string.Empty);

                exportFilename = Path.Combine(folder, $"{CreationTimeStamp.ToString("yyyy-MM-dd-HHmm")}_No_LdgTaxes_with_Remarks (to check and NO import in Proffix).csv");
                listToExport   = proffixDataList.Where(x => (x.FlightBoxData.IsMaintenanceFlight ||
                                                             x.FlightBoxData.IsTowFlight ||
                                                             x.FlightBoxData.IgnoreLandingTax) &&
                                                       string.IsNullOrWhiteSpace(x.FlightBoxData.Remarks) == false)
                                 .ToList();

                if (listToExport.Any())
                {
                    OnLogEventRaised(
                        $"Exportiere Daten mit Bemerkungen zur Prüfung und NICHT importieren in Proffix in Datei: {exportFilename}");
                    var exporter = new ProffixDataCsvExporter(exportFilename, listToExport);
                    exporter.Export();
                    OnLogEventRaised(
                        $"{exporter.NumberOfLinesExported} Daten mit Bemerkungen zur Prüfung und NICHT importieren in Proffix erfolgreich exportiert.");
                }
                else
                {
                    OnLogEventRaised(
                        $"Keine Daten mit Bemerkungen zur Prüfung und NICHT importieren in Proffix exportiert. Datei: {exportFilename} wurde nicht erzeugt!");
                }

                Thread.Sleep(50);
                OnLogEventRaised(string.Empty);

                exportFilename = Path.Combine(folder, $"{CreationTimeStamp.ToString("yyyy-MM-dd-HHmm")}_Heli Sitterdorf.csv");
                listToExport   = proffixDataList.Where(x => x.MemberNumber == "999605" && x.FlightBoxData.IsDepartureMovement == false)
                                 .ToList();

                if (listToExport.Any())
                {
                    OnLogEventRaised($"Exportiere Daten für Heli Sitterdorf in Datei: {exportFilename}");
                    var reportExporter = new ReportExporter(exportFilename, listToExport);
                    reportExporter.Export();
                    OnLogEventRaised(
                        $"{reportExporter.NumberOfLinesExported} Daten für Heli Sitterdorf erfolgreich exportiert.");
                }
                else
                {
                    OnLogEventRaised(
                        $"Keine Daten für Heli Sitterdorf exportiert. Datei: {exportFilename} wurde nicht erzeugt!");
                }

                Thread.Sleep(50);
                OnLogEventRaised(string.Empty);

                exportFilename = Path.Combine(folder, $"{CreationTimeStamp.ToString("yyyy-MM-dd-HHmm")}_Skydive.csv");
                listToExport   = proffixDataList.Where(x => x.MemberNumber == "703100" && x.FlightBoxData.IsDepartureMovement == false)
                                 .ToList();

                if (listToExport.Any())
                {
                    OnLogEventRaised($"Exportiere Daten für Skydive in Datei: {exportFilename}");
                    var reportExporter = new ReportExporter(exportFilename, listToExport);
                    reportExporter.Export();
                    OnLogEventRaised(
                        $"{reportExporter.NumberOfLinesExported} Daten für Skydive erfolgreich exportiert.");
                }
                else
                {
                    OnLogEventRaised(
                        $"Keine Daten für Skydive exportiert. Datei: {exportFilename} wurde nicht erzeugt!");
                }

                Thread.Sleep(50);
                OnLogEventRaised(string.Empty);

                exportFilename = Path.Combine(folder, $"{CreationTimeStamp.ToString("yyyy-MM-dd-HHmm")}_Swiss oldies.csv");
                listToExport   = proffixDataList.Where(x => x.MemberNumber == "28" && x.FlightBoxData.IsDepartureMovement == false)
                                 .ToList();

                if (listToExport.Any())
                {
                    OnLogEventRaised($"Exportiere Daten für Swiss oldies in Datei: {exportFilename}");
                    var reportExporter = new ReportExporter(exportFilename, listToExport);
                    reportExporter.Export();
                    OnLogEventRaised(
                        $"{reportExporter.NumberOfLinesExported} Daten für Swiss oldies erfolgreich exportiert.");
                }
                else
                {
                    OnLogEventRaised(
                        $"Keine Daten für Swiss oldies exportiert. Datei: {exportFilename} wurde nicht erzeugt!");
                }

                Thread.Sleep(50);

                WriteLogFile();

                Thread.Sleep(50);

                ExportFinished?.Invoke(this, EventArgs.Empty);
            }
            catch (Exception e)
            {
                HasExportError     = true;
                ExportErrorMessage = e.Message;
                OnLogEventRaised("Fehler beim Convertieren..." + Environment.NewLine + "Fehlermeldung: " + e.Message);
                ExportFinished?.Invoke(this, EventArgs.Empty);
            }
        }
        private void CalculateLandingTax(ProffixData proffixData)
        {
            // set Article number in Proffix data
            if (proffixData.FlightBoxData.TypeOfTraffic == (int)TypeOfTraffic.Instruction)
            {
                proffixData.ArticleNr = "1039"; //Landetaxen Speck Schulung
            }
            else
            {
                proffixData.ArticleNr = "1037"; //Landetaxen Speck (Charter)
            }

            // calculate quantity of landings in Proffix data
            if (proffixData.FlightBoxData.MovementType == "A") //Arrival
            {
                proffixData.ArticleQuantity = System.Convert.ToDecimal((proffixData.FlightBoxData.NrOfMovements + 1) / 2);
            }
            else if (proffixData.FlightBoxData.MovementType == "V") //circuits
            {
                proffixData.ArticleQuantity = System.Convert.ToDecimal(proffixData.FlightBoxData.NrOfMovements / 2);
            }
            else
            {
                proffixData.ArticleQuantity = 0;
            }

            proffixData.VfsArticleNumber = "1003";
            proffixData.VfsPrice         = 1.0m;
            proffixData.VfsQuantity      = proffixData.ArticleQuantity; //is same formula as for landing tax quantity calculation

            // calculate price for SchSpeck
            if (proffixData.FlightBoxData.IsHomebased && proffixData.FlightBoxData.TypeOfTraffic == (int)TypeOfTraffic.Instruction)
            {
                proffixData.SchHome = 0;
            }
            else
            {
                proffixData.SchHome = 0;
            }

            // calculate price for SchFremd
            if (proffixData.FlightBoxData.TypeOfTraffic == (int)TypeOfTraffic.Instruction &&
                proffixData.FlightBoxData.IsHomebased == false)
            {
                if (proffixData.FlightBoxData.MaxTakeOffWeight < 1001)
                {
                    proffixData.SchExternal = 8.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight < 1251)
                {
                    proffixData.SchExternal = 12.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight < 1501)
                {
                    proffixData.SchExternal = 15.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight < 2001)
                {
                    proffixData.SchExternal = 20.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight > 2000)
                {
                    proffixData.SchExternal = 30.0m;
                }
                else
                {
                    proffixData.SchExternal = 0;
                }
            }
            else
            {
                proffixData.SchExternal = 0;
            }


            // calculate price for HB
            if (proffixData.FlightBoxData.IsHomebased &&
                proffixData.FlightBoxData.TypeOfTraffic != (int)TypeOfTraffic.Instruction)
            {
                if (proffixData.FlightBoxData.MaxTakeOffWeight < 751)
                {
                    proffixData.LdgTaxHomebased = 12.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight < 1001)
                {
                    proffixData.LdgTaxHomebased = 15.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight < 1251)
                {
                    proffixData.LdgTaxHomebased = 17.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight < 1501)
                {
                    proffixData.LdgTaxHomebased = 20.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight < 2001)
                {
                    proffixData.LdgTaxHomebased = 25.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight > 2000)
                {
                    proffixData.LdgTaxHomebased = 35.0m;
                }
                else
                {
                    proffixData.LdgTaxHomebased = 0;
                }
            }
            else
            {
                proffixData.LdgTaxHomebased = 0;
            }


            // calculate price for Fremd
            if (proffixData.FlightBoxData.IsHomebased == false &&
                proffixData.FlightBoxData.TypeOfTraffic != (int)TypeOfTraffic.Instruction)
            {
                if (proffixData.FlightBoxData.MaxTakeOffWeight < 751)
                {
                    proffixData.LdgTaxExternal = 17.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight < 1001)
                {
                    proffixData.LdgTaxExternal = 20.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight < 1251)
                {
                    proffixData.LdgTaxExternal = 22.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight < 1501)
                {
                    proffixData.LdgTaxExternal = 25.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight < 2001)
                {
                    proffixData.LdgTaxExternal = 30.0m;
                }
                else if (proffixData.FlightBoxData.MaxTakeOffWeight > 2000)
                {
                    proffixData.LdgTaxExternal = 40.0m;
                }
                else
                {
                    proffixData.LdgTaxExternal = 0;
                }
            }
            else
            {
                proffixData.LdgTaxExternal = 0;
            }

            if (proffixData.FlightBoxData.Immatriculation == "YLLEV" ||
                proffixData.FlightBoxData.Immatriculation == "LYTED" ||
                proffixData.FlightBoxData.Immatriculation == "LYMHC")
            {
                //Antonov AN-2
                proffixData.LdgTaxExternal = 80.0m;
            }

            if (proffixData.FlightBoxData.Immatriculation == "HBZNP" ||
                proffixData.FlightBoxData.Immatriculation == "HBZNM")
            {
                // Helicopter over 78dB --> double landing tax price

                if (proffixData.SchHome > 0)
                {
                    proffixData.SchHome = proffixData.SchHome * 2;
                }
                if (proffixData.SchExternal > 0)
                {
                    proffixData.SchExternal = proffixData.SchExternal * 2;
                }
                if (proffixData.LdgTaxHomebased > 0)
                {
                    proffixData.LdgTaxHomebased = proffixData.LdgTaxHomebased * 2;
                }
                if (proffixData.LdgTaxExternal > 0)
                {
                    proffixData.LdgTaxExternal = proffixData.LdgTaxExternal * 2;
                }
            }

            //sum up all landing tax fees
            proffixData.ArticlePrice = proffixData.SchHome + proffixData.SchExternal + proffixData.LdgTaxHomebased +
                                       proffixData.LdgTaxExternal;
        }