package de.duehl.basics.io.textfile.dictionary.join;

/*
 * 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 de.duehl.basics.io.Charset;
import de.duehl.basics.io.FileHelper;
import de.duehl.basics.io.textfile.dictionary.Dictionary;
import de.duehl.basics.io.textfile.dictionary.DictionaryEntry;

/**
 * Diese Klasse vereinigt zwei Wörterbücher zu einem einzigen, das die Einträge der beiden
 * zusammenführt.
 *
 * Dazu können bereits vorliegende Wörterbücher übergeben werden, oder es werden zwei Listen mit
 * den Texten im Format des DictionaryFiles aus den Zeilen zweier Textdatei eingelesen und diese
 * zu einem neuen Dictionary vereinigt.
 *
 * Das Format sieht wie folgt aus:
 *
 * Englisches Wort
 *     Deutsches Wort 1
 *     Deutsches Wort 2
 *     Deutsches Wort 3
 *     Deutsches Wort 4
 *
 * Kommt in einer Datenzeile weiter hinten das Kommentarzeichen vor, so wird ab dort abgeschnitten
 * und getrimmt.
 *
 * @version 1.01     2024-05-17
 * @author Christian Dühl
 */

public class DictionaryJoiner {

    /** Das erste zu vereinigende Wörterbuch. */
    private final Dictionary dictionary1;

    /** Das zweite zu vereinigende Wörterbuch. */
    private final Dictionary dictionary2;

    /** Das zusammengesetzte Wörterbuch. */
    private Dictionary joinedDictionary;

    /**
     * Konstruktor für zwei bereits vorliegende Wörterbücher.
     *
     * @param dictionary1
     *            Das erste zu vereinigende Wörterbuch.
     * @param dictionary2
     *            Das zweite zu vereinigende Wörterbuch.
     */
    public DictionaryJoiner(Dictionary dictionary1, Dictionary dictionary2) {
        this.dictionary1 = dictionary1;
        this.dictionary2 = dictionary2;
    }

    /**
     * Konstruktor für zwei Wörterbücher, die aus externen Dateien geladen werden.
     *
     * @param filename1
     *            Name der ersten einzulesenden Datei.
     * @param charset1
     *            Kodierung der ersten einzulesenden Datei.
     * @param filename2
     *            Name der zweiten einzulesenden Datei.
     * @param charset2
     *            Kodierung der zweiten einzulesenden Datei.
     */
    public DictionaryJoiner(String filename1, Charset charset1, String filename2, Charset charset2) {
        dictionary1 = FileHelper.readDictionaryFromNormalTextFile(filename1, charset1);
        dictionary2 = FileHelper.readDictionaryFromNormalTextFile(filename2, charset2);
    }

    /** Vereinigt die beiden Wörterbücher. */
    public void join() {
        joinedDictionary = new Dictionary();
        addDictionary(dictionary1);
        addDictionary(dictionary2);
    }

    private void addDictionary(Dictionary dictionary) {
        for (DictionaryEntry entry : dictionary) {
            addList(entry);
        }
    }

    private void addList(DictionaryEntry entry) {
        String mainWord = entry.getMainWord();
        if (joinedDictionary.containsEntryWithMainWord(mainWord)) {
            DictionaryEntry joinedEntry = joinedDictionary.getEntryWithMainWord(mainWord);
            joinEntries(joinedEntry, entry);
        }
        else {
            addNewEntry(entry);
        }
    }

    private void addNewEntry(DictionaryEntry entry) {
        DictionaryEntry copy = new DictionaryEntry(entry);
        joinedDictionary.addDictionaryEntry(copy);
    }

    private void joinEntries(DictionaryEntry joinedEntry, DictionaryEntry entryToJoin) {
        for (String alternative : entryToJoin.getAlternatives()) {
            if (!joinedEntry.contains(alternative)) {
                joinedEntry.addAlternative(alternative);
            }
        }
    }

    /** Getter für das zusammengesetzte Wörterbuch. */
    public Dictionary getJoinedDictionary() {
        return joinedDictionary;
    }

}
