package de.duehl.vocabulary.japanese.website.update.ownlists.parser;

import java.util.ArrayList;
import java.util.List;

import de.duehl.basics.collections.CollectionsHelper;
import de.duehl.basics.text.NumberString;
import de.duehl.basics.text.Text;
import de.duehl.basics.text.handling.BooleanHandling;
import de.duehl.vocabulary.japanese.website.update.ownlists.data.OwnListInterestAndVersionEntry;

/**
 * Diese Klasse parst den Inhalt der Datei mit den Interessen und den zuletzt gesehenen Versionen
 * der Gruppen von eigenen Listen des Benutzers lokal in seinem Benutzerverzeichnis:
 *     Eigene_Listen_Interessen_und_Versionen.txt
 *
 * @version 1.01     2024-10-05
 * @author Christian Dühl
 */

public class OwnListVersionAndInterestParser {

    /** Der Inhalt der eingelesenen Datei Neuste_Version_Listen.txt. */
    private final String content;

    /** Die interessanten Zeilen des Inhalts der Datei. */
    private List<String> lines;

    /** Gibt an, ob der String mit der Version erfolgreich geparst werden konnte. */
    private boolean success;

    /**
     * Der Grund, warum der String mit der Version nicht geparst werden konnte (nur gefüllt wenn
     * success false ist).
     */
    private String failReason;

    /**
     * Die Liste mit den Interessen und den zuletzt gesehenen Versionen der Gruppen von eigenen
     * Listen des Benutzers.
     */
    private List<OwnListInterestAndVersionEntry> ownListInterestAndVersionEntries;

    /**
     * Konstruktor.
     *
     * @param content
     *            Der Inhalt der eingelesenen Datei Eigene_Listen_Interessen_und_Versionen.txt.
     */
    public OwnListVersionAndInterestParser(String content) {
        this.content = content;
    }

    /** Führt das Parsen durch. */
    public void parse() {
        init();
        splitContent();
        parseLines();
        removeAllEntriesIfErrorOccured();
    }

    private void init() {
        success = true;
        failReason = "";
        ownListInterestAndVersionEntries = new ArrayList<>();
    }

    private void splitContent() {
        lines = Text.splitByLineBreaks(content);
        CollectionsHelper.removeEmptyAndOnlyWhitespaceStringsFromList(lines);
    }

    private void parseLines() {
        for (String line : lines) {
            OwnListInterestAndVersionEntry entry = parseLine(line);
            ownListInterestAndVersionEntries.add(entry);
        }
    }

    private OwnListInterestAndVersionEntry parseLine(String line) {
        try {
            return tryToParseLine(line);
        }
        catch (Exception exception) {
            fail("Die Zeile '" + line + "' lässt sich nicht parsen: " + exception.getMessage());
            return new OwnListInterestAndVersionEntry("", false, -1);
        }
    }

    private OwnListInterestAndVersionEntry tryToParseLine(String line) {
        List<String> parts = Text.splitBySubtraction(line);
        if (parts.size() != 3) {
            throw new RuntimeException("Die Zeile lässt sich nicht an '-' in drei Teile teilen.");
        }

        String groupName = parts.get(0);
        String interestedString = parts.get(1);
        String versionString = parts.get(2);

        boolean interested = BooleanHandling.stringToBoolean(interestedString); // wirft Ausnahme

        if (!NumberString.isDigitSequence(versionString)) {
            throw new RuntimeException("Die Version '" + versionString
                    + "' in der Zeile besteht nicht nur aus Ziffern");
        }

        int version = NumberString.parseInt(versionString);
        return new OwnListInterestAndVersionEntry(groupName, interested, version);
    }

    private void removeAllEntriesIfErrorOccured() {
        if (!success) {
            ownListInterestAndVersionEntries.clear();
        }
    }

    private void fail(String failReason) {
        success = false;
        this.failReason = failReason;
    }

    /** Gibt an, ob der String mit der Version erfolgreich geparst werden konnte. */
    public boolean isSuccess() {
        return success;
    }

    /**
     * Getter für den Grund, warum der String mit der Version nicht geparst werden konnte (nur
     * gefüllt wenn isSuccess() false ist).
     */
    public String getFailReason() {
        return failReason;
    }

    /**
     * Getter für die Liste mit den Interessen und den zuletzt gesehenen Versionen der Gruppen von
     * eigenen Listen des Benutzers.
     */
    public List<OwnListInterestAndVersionEntry> getOwnListInterestAndVersionEntries() {
        return ownListInterestAndVersionEntries;
    }

}
