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

// Anzahl der einzulesenden gueltigen Position
const int MAX_ENTRIES = 5;
// Synonym fuer tuple
// tuple: Position, Titel, Interpret
using entry = std::tuple<int, std::string, std::string>;

// tuple-Feld fuer
entry entries[MAX_ENTRIES];

// Einlesen der Daten aus Datei
int ReadData(std::ifstream& infile)
{
    // Erste MAX_ENTRIES platzierte Titel einlesen
    int counter = 0;
    do
    {
        std::string title, artist, spos;
        unsigned int ipos;
        // Titel einlesen und auf EOF pruefen
        std::getline(infile, title, ';');
        // Wenn Dateiende erreicht,
        if (infile.eof())
            break;
        // Interpret und Position einlesen
        std::getline(infile, artist, ';');
        std::getline(infile, spos, ';');
        // Position string->unsigned int Konvertierung
        std::from_chars(spos.c_str(), spos.c_str() + spos.length(), ipos);
        // Wenn Titel positioniert
        // Daten in tuple ablegen und Zaehler inkr.
        if (ipos)
        {
            std::get<0>(entries[counter]) = ipos;
            std::get<1>(entries[counter]) = title;
            std::get<2>(entries[counter]) = artist;
            counter++;
        }
        // Rest der Zeile ueberspringen
        std::getline(infile, spos);
    } while (counter < MAX_ENTRIES);
    // Anzahl Positionen zurueckgeben
    return counter;
}

// tuple-Daten sortieren (einfach Bubble-Sort)
void Sort()
{
    bool changed;
    do
    {
        changed = false;
        for (auto index = 0; index < MAX_ENTRIES - 1; index++)
        {
            if (entries[index] > entries[index + 1])
            {
                entry tmp = std::move(entries[index]);
                entries[index] = std::move(entries[index + 1]);
                entries[index + 1] = std::move(tmp);
                changed = true;
            }
        }
    } while (changed);
}

// tuple-Daten ausgeben
void Print()
{
    for (auto index = 0; index < MAX_ENTRIES; index++)
        std::println("P:{}, T:{}, A:{}",
            std::get<0>(entries[index]),
            std::get<1>(entries[index]),
            std::get<2>(entries[index]));
}

int main()
{
    std::string lineIn;
    // Eingabedatei oeffnen und eventl. Fehler abfangen
    std::ifstream infile("../../04_Data/swr1_hitparade.csv");
    if (!infile)
    {
        std::println("Fehler beim Oeffnen der Datei!");
        exit(1);
    }
    // 1. Zeile ueberspringen, enthaelt Spaltenueberschriften
    std::getline(infile, lineIn);
    // Daten einlesen
    if (ReadData(infile) != MAX_ENTRIES)
        std::println("Keine {} Eintraege gefunden!", MAX_ENTRIES);
    else
    {
        // Daten ausgeben, sortieren und erneut ausgeben
        Print();
        std::println("------------------------");
        Sort();
        Print();
    }
    // Datei auch wieder schliessen!
    infile.close();
}
