package de.duehl.basics.autodetect;

/*
 * Copyright 2024 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;
import de.duehl.basics.text.data.FoundSearch;

/**
 * Diese Klasse stellt Hilfsmethoden rund um die automatischen Bearbeitung zur Verfügung.
 *
 * @version 1.01     2024-02-08
 * @author Christian Dühl
 */

public class AutoDetectionHelper {

    /** Das doppelte Anführungszeichen. */
    public static final String DOUBLE_QUOTE = "\"";

    /**
     * Erstellt einen Platzhalter für eine Entität in der Form
     * <tt>&lt;&lt;front:position&gt;&gt;</tt> wie z.B. <tt>&lt;&lt;street:7&gt;&gt;</tt>
     *
     * @param replacementFrontPart
     *            Vorderer Teil, im Beispiel 'street'.
     * @param replacementNumber
     *            Die Position (1-basiert), im Beispiel '7'.
     * @return Gibt den erzeugten Platzhalter zurück.
     */
    public static String createEntity(String replacementFrontPart, String replacementNumber) {
        return "<<" + replacementFrontPart + ":" + replacementNumber + ">>";
    }

    /**
     * Erstellt einen Platzhalter für eine Entität in der Form
     * <tt>&lt;&lt;front:position&gt;&gt;</tt> wie z.B. <tt>&lt;&lt;street:7&gt;&gt;</tt>
     *
     * @param replacementFrontPart
     *            Vorderer Teil, im Beispiel 'street'.
     * @param replacementNumber
     *            Die Position (1-basiert), im Beispiel '7'.
     * @return Gibt den erzeugten Platzhalter zurück.
     */
    public static String createEntity(String replacementFrontPart, int replacementNumber) {
        return createEntity(replacementFrontPart, Integer.toString(replacementNumber));
    }

    /**
     * Gibt alle gefundenen Suchbegriffe sortiert nach dem Vorkommen im Eingabetext zurück.
     *
     * @param input
     *            Eingabetext in dem gesucht wird.
     * @param searchWords
     *            Liste der Suchbegriffe, es wird erwartet, dass diese absteigend nach der Länge
     *            sortiert ist.
     * @return Liste mit den Fundstellen.
     */
    public static List<FoundSearch> findAllSearchWords(String input, List<String> searchWords) {
        List<FoundSearch> foundSearches = new ArrayList<>();

        String output = input;

        boolean search = true;
        while(search) {
            search = false;
            for (String searchWord : searchWords) {
                int index = output.indexOf(searchWord);
                if (index > -1) {
                    search = true;
                    FoundSearch foundSearch = new FoundSearch(index, searchWord);
                    foundSearches.add(foundSearch);
                    String before = output.substring(0, index);
                    String middle = Text.multipleString("#", searchWord.length());
                    String after = output.substring(index + searchWord.length());
                    output = before + middle + after;
                    break;
                }
            }
        }

        FoundSearch.sortFoundSearchListByIndex(foundSearches);

        return foundSearches;
    }

    /**
     * Gibt alle gefundenen Suchbegriffe sortiert nach dem Vorkommen im Eingabetext zurück.
     *
     * @param input
     *            Eingabetext in dem gesucht wird.
     * @param searchWords
     *            Liste der Suchbegriffe, es wird erwartet, dass diese absteigend nach der Länge
     *            sortiert ist.
     * @return Liste mit den Fundstellen.
     */
    public static List<FoundSearch> findAllSearchWordsNotStartigOrEndingInWord(String input,
            List<String> searchWords) {
        List<FoundSearch> foundSearches = new ArrayList<>();

        String output = input;

        boolean search = true;
        while(search) {
            search = false;
            for (String searchWord : searchWords) {
                int index = output.indexOf(searchWord);
                if (index > -1) {
                    String before = output.substring(0, index);
                    String middle = Text.multipleString("#", searchWord.length());
                    String after = output.substring(index + searchWord.length());

                    if (!Text.endsWithLetter(before) && !Text.startsWithLetter(after)) {
                        search = true;
                        FoundSearch foundSearch = new FoundSearch(index, searchWord);
                        foundSearches.add(foundSearch);
                        output = before + middle + after;
                        break;
                    }
                }
            }
        }

        FoundSearch.sortFoundSearchListByIndex(foundSearches);

        return foundSearches;
    }

    /**
     * Korrigiert Strings mit doppelten Anführungszeichen darin.
     *
     * @param input
     *            Eingabe mit ggf. doppelten Anführungszeichen.
     * @return Korrigierte Ausgabe.
     */
    public static String correctQuotes(String input) { // TODO testen
        String output = input;

        List<Integer> quoteIndices = Text.findAllPositions(DOUBLE_QUOTE, output);
        if (quoteIndices.size() % 2 == 0
                && output.startsWith(DOUBLE_QUOTE)
                && output.endsWith(DOUBLE_QUOTE)) {
            output = output.substring(1, output.length() - 1);
            quoteIndices = Text.findAllPositions(DOUBLE_QUOTE, output);
        }

        if (quoteIndices.size() == 4) {
            int index1 = quoteIndices.get(0);
            int index2 = quoteIndices.get(1);
            int index3 = quoteIndices.get(2);
            int index4 = quoteIndices.get(3);
            if (index1 + 1 == index2 && index3 + 1 == index4) {
                output = output.replace("\"\"", DOUBLE_QUOTE);
            }
        }

        return output;
    }

}
