package de.duehl.basics.autodetect.ent.multiple;

/*
 * 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.Collections;
import java.util.List;

import de.duehl.basics.autodetect.AutoDetectionHelper;
import de.duehl.basics.text.Text;
import de.duehl.basics.text.data.FoundSearch;

/**
 * Diese Klasse findet im Text (ent) alle bekannten Begriffe einer Art und sammelt diese in einer
 * Liste. Dabei werden die Begriffe in ent durch Platzhalter der Form <<function:17>> ersetzt und
 * Kommentare zur Auffindung der Begriffe gesammelt.
 *
 * @version 1.01     2024-02-08
 * @author Christian Dühl
 */

public class MultipleEntityReplacerWithThingsFinder extends MultipleEntityReplacer {

    /** Klasse, die Begriffe in ent finden kann, ohne dies zu verändern. */
    private final DetectMultipleThingsFinder thingsFinder;

    /** Die Anzahl der Begriffe, die zuvor bereits erkannt und in ent ersetzt wurden. */
    private final int numberOfThingsDetectedBefore;

    /**
     * Konstruktor.
     *
     * @param ent
     *            Ursprünglich der rohe Text, dieser wird/wurde bei der Analyse aber verändert und
     *            Teile durch die Entitäten wie <<street:2>> ersetzt.
     * @param replacementFrontPart
     *            Kürzel das vorn vor der Position im Entitätenplatzhalter steht, z.B. 'func' in
     *            <<func:3>>.
     * @param thingsFinder
     *            Klasse, die Begriffe in ent finden kann, ohne dies zu verändern.
     */
    public MultipleEntityReplacerWithThingsFinder(String ent, String replacementFrontPart,
            DetectMultipleThingsFinder thingsFinder) {
        this(ent, replacementFrontPart, thingsFinder, 0);
    }

    /**
     * Konstruktor.
     *
     * @param ent
     *            Ursprünglich der rohe Text, dieser wird/wurde bei der Analyse aber verändert und
     *            Teile durch die Entitäten wie <<street:2>> ersetzt.
     * @param replacementFrontPart
     *            Kürzel das vorn vor der Position im Entitätenplatzhalter steht, z.B. 'func' in
     *            <<func:3>>.
     * @param thingsFinder
     *            Klasse, die Begriffe in ent finden kann, ohne dies zu verändern.
     * @param numberOfThingsDetectedBefore
     *            Die Anzahl der Begriffe, die zuvor bereits erkannt und in ent ersetzt wurden.
     */
    public MultipleEntityReplacerWithThingsFinder(String ent, String replacementFrontPart,
            DetectMultipleThingsFinder thingsFinder, int numberOfThingsDetectedBefore) {
        super(ent, replacementFrontPart);
        this.thingsFinder = thingsFinder;
        this.numberOfThingsDetectedBefore = numberOfThingsDetectedBefore;
    }

    /** Sucht, sammelt und ersetzt in ent. */
    @Override
    public void replace() {
        standardDetect();
    }

    protected final void standardDetect() {
        /* Bestimmt die Liste aller erkannten Begriffe in der Reihenfolge des Vorkommens in ent: */
        List<FoundSearch> foundSearches = thingsFinder.findAllThings(ent);

        /* Wir machen das rückwärts, denn anderenfalls müsste man die Indices alle umrechnen: */
        Collections.reverse(foundSearches);

        replaceFoundSearchesInEnt(foundSearches);

        /* Nun drehen wir die befüllte Liste wieder richtigherum: */
        Collections.reverse(valueList);
    }

    private void replaceFoundSearchesInEnt(List<FoundSearch> foundSearches) {
        List<FoundSearch> foundSearchesWeWantToReplace = new ArrayList<>();
        for (FoundSearch foundSearch : foundSearches) {
            int end = foundSearch.getEnd();
            String after = ent.substring(end);
            if (!Text.startsWithLowercaseLetter(after)) { // sonst haben wir nur den Anfang eines Wortes
                foundSearchesWeWantToReplace.add(foundSearch);
            }
        }

        int replacementNumber = numberOfThingsDetectedBefore + foundSearchesWeWantToReplace.size();
        for (FoundSearch foundSearch : foundSearchesWeWantToReplace) {
            String search = foundSearch.getSearch();
            int start = foundSearch.getIndex();
            int end = foundSearch.getEnd();
            String before = ent.substring(0, start);
            String after = ent.substring(end);

            valueList.add(search);
            String replacement = AutoDetectionHelper.createEntity(replacementFrontPart,
                    replacementNumber);
            --replacementNumber;
            ent = before + replacement + after;
            appendAutoComment("[" + replacementFrontPart + " detected]");
        }
    }

}
