package de.duehl.vocabulary.japanese.data;

import java.util.List;

import javax.swing.filechooser.FileFilter;

import de.duehl.basics.datetime.date.ImmutualDate;
import de.duehl.basics.io.FileHelper;
import de.duehl.basics.text.Text;
import de.duehl.swing.ui.GuiTools;
import de.duehl.vocabulary.japanese.common.persistence.data.OwnListPersistanceData;

import static de.duehl.vocabulary.japanese.common.persistence.SessionManager.VOCABLE_TRAINER_DIRECTORY;

/**
 * Diese Klasse stellt eine eigene Vokabelliste dar. Im wesentlichen ist das inhaltlich das gleiche
 * wie ein Vokabular, allerdings ist die Kategorie fix und statt der 'Beschreibung' (des
 * Vokabulars) wird hier der 'Name' (der Vokabelliste) verwendet.
 *
 * Wir speichern den Namen auch in der Beschreibung, da die VocabularyBar mit Vocabulary-Objekten
 * arbeitet und daher die Beschreibung abfragt. Daher wird im Konstruktor und in setName() auch die
 * Beschreibung gefüllt.
 *
 * Dinge wie das Datum der ältesten Vokabel und die Kategorie sollen hier nicht verwendet werden,
 * daher werden die Getter/Setter überschrieben und eine Ausnahme geworfen.
 *
 * Die Vokabellisten werden im Benutzerverzeichnis in ~/own_vocable_lists gespeichert. Dazu gibt
 * es eine Datei mit der Auflistung aller Vokabellisten in der richtigen Reihenfolge, sowie je
 * eine Datei pro Liste, die eine Liste der keys enthält, pro Zeile einen.
 *
 * @version 1.01     2025-06-27
 * @author Christian Dühl
 */

public class OwnList extends Vocabulary {

    /** Das benutzerspezifische Verzeichnis, in dem die eigenen Listen liegen. */
    public static final String OWN_LIST_DIRECTORY =
            FileHelper.concatPathes(VOCABLE_TRAINER_DIRECTORY, "own_vocable_lists");

    /** Die Extension für die Dateien mit den Vokabellisten. */
    public static final String OWN_LISTS_EXTENSION = ".owl";

    private static final ImmutualDate NOT_SORTED_BY_FIRST_SEEN_DATE =
            new ImmutualDate("21.03.2024");


    /** Der Name der Vokabelliste. */
    private String name;

    /**
     * Konstruktor.
     *
     * @param name
     *            Der Name der Vokabelliste.
     * @param category
     *            Die Kategorie zu der die Vokabelliste gehört.
     * @param subCategory
     *            Die Unterkategorie zu der die Vokabelliste gehört.
     * @param vocables
     *            Die Liste der Vokabeln die zur Vokabelliste gehören.
     */
    public OwnList(String name, String category, String subCategory, List<Vocable> vocables) {
        super(createDescriptionFromName(name), vocables, category, subCategory);
        // Siehe Erklärung im Kopf der Klasse.

        this.name = name;
    }

    /** Erzeugt aus dem Namen (mit Unterstrichen) eine Beschreibung (ohne Unterstriche). */
    public static String createDescriptionFromName(String name) {
        String description = name;
        description = description.replace("_", " ");
        return description;
    }

    /** Getter für den Namen der Vokabelliste. */
    public String getName() {
        return name;
    }

    /** Setter für den Namen der Vokabelliste. */
    public void setName(String name) {
        this.name = name;

        super.setDescription(name); // Siehe Erklärung im Kopf der Klasse.
    }

    /**
     * Getter für das früheste Datum an dem eine Vokabel aus dem Vokabular das erste Mal eingelesen
     * wurde.
     *
     * Das macht hier in einer Liste so gar keinen Sinn, daher wird ein festes Datum zurückgegeben.
     */
    @Override
    public ImmutualDate getFirstSeenDate() {
        return NOT_SORTED_BY_FIRST_SEEN_DATE;
    }

    /**
     * Setter für das früheste Datum an dem eine Vokabel aus dem Vokabular das erste Mal eingelesen
     * wurde.
     */
    @Override
    public void setFirstSeenDate(ImmutualDate firstSeenDate) {
        throw new RuntimeException("do not use");
    }

    /** Ermittelt den passenden Dateinamen im passenden Verzeichnis der Benutzers. */
    public String determineFilename() {
        return determineFilename(name);
    }

    /** Ermittelt zum Namen den passenden Dateinamen im passenden Verzeichnis der Benutzers. */
    public static String determineFilename(String name) {
        String bareFilename = Text.createJavaVariableName(name) + OWN_LISTS_EXTENSION;
        String filename = FileHelper.concatPathes(OWN_LIST_DIRECTORY, bareFilename);
        return filename;
    }

    /** Erzeugt das Verzeichnis für die Vokabellisten im Verzeichnis der Benutzers. */
    public static void createOwnListDirectoryIfNotExisting() {
        FileHelper.createDirectoryIfNotExists(OWN_LIST_DIRECTORY);
    }

    /**
     * Ermittelt aus dem Dateinamen für eine solche Liste den Teil, der der Java-Variante des
     * Listennamens entspricht.
     */
    public static String createJavaFormOfNameFromFilename(String filename) {
        String bareFilename = FileHelper.getBareName(filename);
        if (bareFilename.endsWith(OWN_LISTS_EXTENSION)) {
            return Text.removeTextAtEndIfEndsWith(bareFilename, OWN_LISTS_EXTENSION);
        }
        else {
            return "";
        }
    }

    // nicht benutzt und daher noch nicht getestet!
    public static boolean belongsFilenameToName(String filename, String name) {
        String bareFilename = FileHelper.getBareName(filename);
        if (bareFilename.endsWith(OWN_LISTS_EXTENSION)) {
            String nameInJavaForm =
                    Text.removeTextAtEndIfEndsWith(bareFilename, OWN_LISTS_EXTENSION);
            String javaFormOfName = Text.createJavaVariableName(name);
            return nameInJavaForm.equals(javaFormOfName);
        }
        else {
            return false;
        }
    }

    /** Erzeugt einen FileFilter für Vokabellisten-Dateien. */
    public static FileFilter createFileFilter() {
        return GuiTools.createExtensionFileFilter(OWN_LISTS_EXTENSION);
    }

    /** Erzeugt ein persistent speicherbares Objekt aus der Liste. */
    public OwnListPersistanceData toOwnListPersistanceData() {
        OwnListPersistanceData data = new OwnListPersistanceData();
        data.setCategory(getCategory());
        data.setSubCategory(getSubCategory());
        data.setName(name);
        return data;
    }

    private static final String LERNLISTE = "Lernliste";

    /** Gibt an, ob die Liste eine Lernliste ist. */
    public boolean isLernliste() {
        return name.contains(LERNLISTE)
                || getSubCategory().contains(LERNLISTE)
                || getCategory().contains(LERNLISTE);
    }

    @Override
    public String toString() {
        return "OwnList ["
                + "category=" + getCategory() + ", "
                + "subCategory=" + getSubCategory() + ", "
                + "name=" + name + ""
                + "]";
    }

}
