#include <print>
#include <string>
#include <charconv>
#include <fstream>

// Datei mit der SWR1 Hitparade
const char* const FILENAME = "../../04_Data/swr1_hitparade.csv";
// Anzahl der Jahre, als Konstante vorgegeben da noch
// keine dynamischen Felder/Container behandelt wurden
const auto NOOFYEARS = 26;
// Anzahl der auszuwertenden Hitparaden-Eintraege
const auto MAXSONGS = 15;

// Funktion zum Umwandeln der Daten im String in numerische Werte
// data: string mit den durch Semikolon getrennten Daten
// positions: Feld zur Aufnahme der numerischen Werte aus dem string
// size: Anzahl der Daten im string
// Return: true = kein Fehler bei den Konvertierungen
//         false = Fehler bei mind. einer Konvertierung
bool DecodeString(const std::string& data, unsigned int *positions, unsigned int size)
{
    std::from_chars_result res;             // Ergebnis-Struktur fuer from_chars()
    res.ptr = data.c_str();                 // Zeiger auf Anfang und Ende des Strings
    auto stringEnd = data.c_str() + data.length();
    
    // Alle Daten konvertieren
    decltype(size) index = 0;
    for(; index != size; ++index)
    {
        // Datum in numerischen Wert konvertieren und ablegen
        res = std::from_chars(res.ptr, stringEnd, positions[index]);
        // Wenn kein Fehler bei der Konvertierung
        if (res.ec == std::errc())
            // res.ptr zeigt auf das naechste Zeichen im string
            // das nicht konvertiert werden konnte (gleich Semikolon)
            // +1 um das Semikolon zu ueberspringen
            res.ptr++;
        else
            // Bei Fehler, Konvertierung abbrechen
            break;
    }
    // Wenn Fehler aufgetreten, dessen Position ausgeben und false zurueckliefern
    if (res.ec != std::errc())
    {
        std::println("Fehler an Position {}", index);
        return false;
    }
    else
        // Alles ok, true zurueckgeben
        return true;
}


int main()
{
    // Hitparaden-Datei oeffnen
    std::ifstream infile(FILENAME);
    if (!infile)
    {
        std::println("Datei {} konnte nicht geoeffnet werden", FILENAME);
        exit(1);
    }

    std::string title;              // Titel des Songs
    std::string artist;             // Interpret
    std::string posLine;            // string mit dem Platzierungen
                               
    unsigned int pos[NOOFYEARS];    // Platzierungen
    unsigned int years[NOOFYEARS];  // Hitparadenjahre

    // 1. Zeile der Datei auswerten (Titelzeile)
    // Zeile enthaelt "title;interpret;<jahr1>;....;<jahr24>"
    std::getline(infile, title, ';');       // Titel und Interpret verwerfen
    std::getline(infile, artist, ';');
    std::getline(infile, posLine);          // Jahresangaben als string einlesen

    // Jahresangaben in numerische Daten konvertieren und im Feld years ablegen
    // Wenn Fehler aufgetreten, Programm beeenden
    if (!DecodeString(posLine, years, NOOFYEARS))
    {
        std::println("Fehler beim Einlesen der Jahreszahlen");
        exit(1);
    }

    auto counter = 0U;              // Zaehler fuer Anzahl der eingelesene Eintraege

    // MAXSONGS Eintraege aus der Hitparaden-Datei einlesen
    do
    {
        // Titel einlesen und pruefen, of EOF erreicht
        std::getline(infile, title, ';');
        if (!infile.eof())
        {
            // Interpret einlesen
            std::getline(infile, artist, ';');
            // string mit den Hitparaden-Positionen einlesen
            std::getline(infile, posLine);
            // Positionen im String in numerische Werte konvertieren und in pos ablegen
            // Wenn kein Konvertierungsfehler aufgetreten
            if (DecodeString(posLine, pos, NOOFYEARS))
            {
                // Hoechste Position des Titel suchen
                unsigned int maxPos = 1000;     // 1 = hoechst moeglich Position!
                unsigned int maxYear = 0;
                for (auto index=0; index != NOOFYEARS; ++index)
                {
                    if ((pos[index] < maxPos) && (pos[index] != 0))
                    {
                        maxPos = pos[index];
                        maxYear = years[index];
                    }
                }
                // Titel, Interpret und hoechste Position ausgeben
                std::println("{} mit '{}', Pos:{}({})", artist, title, maxPos, maxYear);
            }
            else
            {
                std::println("Fehler beim Dekodieren");
                break;
            }
            ++counter;              // Anzahl der eingelesenen Titel erhoehen
        }
    } while ((counter < MAXSONGS) && (!infile.eof()));

    // Hitparaden-Datei wieder schliessen
    infile.close();
}
