package de.duehl.basics.io.textfile;

/*
 * Copyright 2025 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

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

import de.duehl.basics.text.Text;

/**
 * Diese Klasse liest eine Liste mit den Texten aus den Zeilen einer Textdatei ein.
 *
 * Die Zeilen werden getrimmt. Dabei werden leere Zeilen und solche, die mit dem Kommentarzeichen
 * (ggf., nach Leerraum) überlesen. Kommt in einer Datenzeile weiter hinten das Kommentarzeichen
 * vor, so wird ab dort abgeschnitten und getrimmt.
 *
 * @version 1.01     2025-01-14
 * @author Christian Dühl
 */

public class StringsFromTextFileReader {

    /** Der Reader, der zum Einlesen der Datei verwendet wird. */
    private final FullTextFileReader reader;

    /** Das Kommentarzeichen. */
    private final String commentChar;

    /** Liste mit den ausgelesenen Texten, die hier aufgebaut wird. */
    private List<String> strings;

    /** Gibt an, ob der Reader ruhig sein soll. */
    private boolean quiet;

    /** Gibt an, ob Leerzeilen mit in das Ergebnis sollen. */
    private boolean includeBlankLinesIntoResult;

    /**
     * Gibt an, ob die eingelesenen Zeilen vorn und hinten von Leerzeichen befreit werden.
     * Kommentare werden hinter den Werten in jedem Fall entfernt.
     */
    private boolean trimLines;

    /** Gibt an, ob die eingelesenen Zeilen in Kleinbuchstaben gewandelt werden. */
    private boolean toLowerCase;

    /** Gerade analysierte Zeile. */
    private String outputLine;

    /**
     * Konstruktor.
     *
     * @param reader
     *            Der Reader, der zum Einlesen der Datei verwendet wird.
     * @param commentChar
     *            Das Kommentarzeichen.
     */
    public StringsFromTextFileReader(FullTextFileReader reader, String commentChar) {
        this.reader = reader;
        this.commentChar = commentChar;

        quiet = false;
        includeBlankLinesIntoResult = false;
        trimLines = true;
        toLowerCase = false;
    }

    /** Legt fest, dass der Reader ruhig sein soll. */
    public void beQuiet() {
        quiet = true;
    }

    /** Legt fest, dass Leerzeilen mit in das Ergebnis sollen. */
    public void includeBlankLinesIntoResult() {
        includeBlankLinesIntoResult = true;
    }

    /**
     * Gibt an, dass die eingelesenen Zeilen in Kleinbuchstaben gewandelt werden.
     *
     * Hierbei wird Locale.GERMAN eingesetzt.
     */
    public void changeToLowerCase() {
        toLowerCase = true;
    }

    /**
     * Gibt an, dass die eingelesenen Zeilen vorn und hinten nicht von Leerzeichen befreit werden.
     *
     * Kommentare werden hinter den Werten in jedem Fall entfernt.
     */
    public void doNotTrimLines() {
        trimLines = false;
    }

    /** Liest die Daten aus der Datei ein. */
    public List<String> read() {
        strings = new ArrayList<>();

        if (quiet) {
            reader.beQuiet();
        }
        reader.read(line -> analyseLine(line));

        return strings;
    }

    private void analyseLine(String line) {
        outputLine = trimLines ? line.trim() : line;

        if (doNotAnalyseLine()) {
            return;
        }

        removeCommentFromLine();
        toLowerCase();

        strings.add(outputLine);
    }

    private boolean doNotAnalyseLine() {
        return outputLine.isEmpty() && !includeBlankLinesIntoResult
                || outputLine.startsWith(commentChar);
    }

    private void removeCommentFromLine() {
        int commentIndex = outputLine.indexOf(commentChar);
        if (commentIndex > -1) {
            outputLine = outputLine.substring(0, commentIndex);
            if (trimLines) {
                outputLine = outputLine.trim();
            }
        }
    }

    private void toLowerCase() {
        if (toLowerCase) {
            outputLine = Text.toLowerCase(outputLine);
        }
    }

    /** Getter für das Kommentarzeichen. */
    public String getCommentChar() {
        return commentChar;
    }

    /** Getter für den Namen der einzulesenden Datei. */
    public String getFilename() {
        return reader.getFilename();
    }

    /** Liefert während der Bearbeitung der Zeilen die Zeilennummer. */
    public int getLineNumber() {
        return reader.getLineNumber();
    }

}
