package de.duehl.basics.autodetect.tools;

/*
 * 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 static org.junit.Assert.*;

import java.util.List;
import java.util.regex.Pattern;

import org.junit.Test;

import de.duehl.basics.collections.CollectionsHelper;

public class EntityJoinerTest {

    private static final String FORENAME_REPLACE_FRONT_PART = "vn";
    private static final String SURNAME_REPLACE_FRONT_PART = "nn";
    private static final String TITLE_ACADEMIC_REPLACE_FRONT_PART = "title";

    private static final String VN_REGEX = "<<" + FORENAME_REPLACE_FRONT_PART + ":(\\d+)>>";
    private static final String NN_REGEX = "<<" + SURNAME_REPLACE_FRONT_PART + ":(\\d+)>>";
    private static final String TITLE_REGEX = "<<" + TITLE_ACADEMIC_REPLACE_FRONT_PART + ":(\\d+)>>";

    private static final String PERSON_SEPARATOR_REGEX = "(?:[;,\\|]| und )";
    private static final String RUBBISH = "<<rubbish>>";
    private static final String OPTIONAL_RUBBISH_REGEX = "(?: ?" + RUBBISH + " ?)*";
    private static final String END_OR_PERSON_SEPARATOR_REGEX =
            OPTIONAL_RUBBISH_REGEX + "(?=$| ?" + PERSON_SEPARATOR_REGEX + ")";


    @Test
    public void joinForenamesWithHyphenOwn() { // selbst ausgedachtes Beispiel
        String ent = "Dr. <<vn:1>>-<<vn:2>>, Müller, Hamburg, *01.02.1983";
        List<String> valueList = CollectionsHelper.buildListFrom("Karl", "Heinz");
        Pattern pattern = Pattern.compile("(" + VN_REGEX + "(-)" + VN_REGEX + ")");
        String autoCommentAdditional = EntityJoiner.createStandardAdditionalComment(
                FORENAME_REPLACE_FRONT_PART, "-");

        EntityJoiner joiner = new EntityJoiner(ent, FORENAME_REPLACE_FRONT_PART,
                pattern, valueList, autoCommentAdditional);
        joiner.join();

        String actualEnt = joiner.getEnt();
        String expectedEnt = "Dr. <<vn:1>>, Müller, Hamburg, *01.02.1983";
        assertEquals(expectedEnt, actualEnt);

        List<String> expectedValueList = CollectionsHelper.buildListFrom("Karl-Heinz");
        assertEquals(expectedValueList, valueList);

        String actualAutoComment = joiner.getAutoComment();
        String expectedAutoComment = " [vn-vn joined]";
        assertEquals(expectedAutoComment, actualAutoComment);
    }

    @Test
    public void joinForenamesWithHyphen() { // aus DetectForenamesViaList
        String ent = "Prof. Dr. <<vn:1>>-<<vn:2>>, Müller, Hamburg, *01.02.1983";
        List<String> valueList = CollectionsHelper.buildListFrom("Karl", "Heinz");
        Pattern pattern = Pattern.compile("(" + VN_REGEX + "(-)" + VN_REGEX + ")");
        String autoCommentAdditional = EntityJoiner.createStandardAdditionalComment(
                FORENAME_REPLACE_FRONT_PART, "-");

        EntityJoiner joiner = new EntityJoiner(ent, FORENAME_REPLACE_FRONT_PART,
                pattern, valueList, autoCommentAdditional);
        joiner.join();

        String actualEnt = joiner.getEnt();
        String expectedEnt = "Prof. Dr. <<vn:1>>, Müller, Hamburg, *01.02.1983";
        assertEquals(expectedEnt, actualEnt);

        List<String> expectedValueList = CollectionsHelper.buildListFrom("Karl-Heinz");
        assertEquals(expectedValueList, valueList);

        String actualAutoComment = joiner.getAutoComment();
        String expectedAutoComment = " [vn-vn joined]";
        assertEquals(expectedAutoComment, actualAutoComment);
    }

    @Test
    public void joinSurnamesWithHyphen() { // aus DetectSurnamesViaList
        String ent = "<<nn:1>>-<<nn:2>>, <<vn:1>>, Hamburg, *01.02.1983";
        List<String> valueList = CollectionsHelper.buildListFrom("Maier", "Hamberger");
        Pattern pattern = Pattern.compile("(" + NN_REGEX + "(-)" + NN_REGEX + ")");
        String autoCommentAdditional = EntityJoiner.createStandardAdditionalComment(
                SURNAME_REPLACE_FRONT_PART, "-");

        EntityJoiner joiner = new EntityJoiner(ent, SURNAME_REPLACE_FRONT_PART,
                pattern, valueList, autoCommentAdditional);
        joiner.join();

        String actualEnt = joiner.getEnt();
        String expectedEnt = "<<nn:1>>, <<vn:1>>, Hamburg, *01.02.1983";
        assertEquals(expectedEnt, actualEnt);

        List<String> expectedValueList = CollectionsHelper.buildListFrom("Maier-Hamberger");
        assertEquals(expectedValueList, valueList);

        String actualAutoComment = joiner.getAutoComment();
        String expectedAutoComment = " [nn-nn joined]";
        assertEquals(expectedAutoComment, actualAutoComment);
    }

    @Test
    public void joinForenamesBeforeSurnameWithSpaces() { // aus NamesWorkerBAfterAristocratical
        String ent = "<<vn:1>> <<vn:2>> <<nn:1>>, Hamburg, *01.02.1983";
        List<String> valueList = CollectionsHelper.buildListFrom("Karl", "Heinz");
        Pattern pattern = Pattern.compile("(" + VN_REGEX + "( )" + VN_REGEX + ") " + NN_REGEX);
        String autoCommentAdditional = "[forenames joined]";

        EntityJoiner joiner = new EntityJoiner(ent, FORENAME_REPLACE_FRONT_PART,
                pattern, valueList, autoCommentAdditional);
        joiner.join();

        String actualEnt = joiner.getEnt();
        String expectedEnt = "<<vn:1>> <<nn:1>>, Hamburg, *01.02.1983";
        assertEquals(expectedEnt, actualEnt);

        List<String> expectedValueList = CollectionsHelper.buildListFrom("Karl Heinz");
        assertEquals(expectedValueList, valueList);

        String actualAutoComment = joiner.getAutoComment();
        String expectedAutoComment = " [forenames joined]";
        assertEquals(expectedAutoComment, actualAutoComment);
    }

    @Test
    public void joinSurnamesAfterForenameWithSpace() {
        // aus NamesWorkerBAfterAristocratical, dort allerdings mit eigenem Kommentar.
        String ent = "<<vn:1>> <<nn:1>> <<nn:2>>, Hamburg, *01.02.1983";
        List<String> valueList = CollectionsHelper.buildListFrom("Maier", "Hamberger");
        Pattern pattern = Pattern.compile(VN_REGEX + " (" + NN_REGEX + "( )" + NN_REGEX + ")"
                + END_OR_PERSON_SEPARATOR_REGEX);
        String autoCommentAdditional = EntityJoiner.createStandardAdditionalComment(
                SURNAME_REPLACE_FRONT_PART, " ");

        EntityJoiner joiner = new EntityJoiner(ent, SURNAME_REPLACE_FRONT_PART,
                pattern, valueList, autoCommentAdditional);
        joiner.setBraceGroupNumber(2); // davor ist die Nummer des Vornamens
        joiner.join();

        String actualEnt = joiner.getEnt();
        String expectedEnt = "<<vn:1>> <<nn:1>>, Hamburg, *01.02.1983";
        assertEquals(expectedEnt, actualEnt);

        List<String> expectedValueList = CollectionsHelper.buildListFrom("Maier Hamberger");
        assertEquals(expectedValueList, valueList);

        String actualAutoComment = joiner.getAutoComment();
        String expectedAutoComment = " [nn nn joined]";
        assertEquals(expectedAutoComment, actualAutoComment);
    }

    @Test
    public void joinSurnamesAfterForenameWithSpaceWithOwnComment() {
        // aus NamesWorkerBAfterAristocratical
        String ent = "<<vn:1>> <<nn:1>> <<nn:2>>, Hamburg, *01.02.1983";
        List<String> valueList = CollectionsHelper.buildListFrom("Maier", "Hamberger");
        Pattern pattern = Pattern.compile(VN_REGEX + " (" + NN_REGEX + "( )" + NN_REGEX + ")"
                + END_OR_PERSON_SEPARATOR_REGEX);
        String autoCommentAdditional = "[surnames joined]";

        EntityJoiner joiner = new EntityJoiner(ent, SURNAME_REPLACE_FRONT_PART,
                pattern, valueList, autoCommentAdditional);
        joiner.setBraceGroupNumber(2); // davor ist die Nummer des Vornamens
        joiner.join();

        String actualEnt = joiner.getEnt();
        String expectedEnt = "<<vn:1>> <<nn:1>>, Hamburg, *01.02.1983";
        assertEquals(expectedEnt, actualEnt);

        List<String> expectedValueList = CollectionsHelper.buildListFrom("Maier Hamberger");
        assertEquals(expectedValueList, valueList);

        String actualAutoComment = joiner.getAutoComment();
        String expectedAutoComment = " [surnames joined]";
        assertEquals(expectedAutoComment, actualAutoComment);
    }


    @Test
    public void joinAcademicTitlesWithSpaces() { // aus DetectTitlesAcademicViaList
        String ent = "<<title:1>> <<title:2>> <<nn:1>>, <<vn:1>> , Hamburg, *01.02.1983";
        List<String> valueList = CollectionsHelper.buildListFrom("Prof.", "Dr.");
        Pattern pattern = Pattern.compile("(" + TITLE_REGEX + "( )" + TITLE_REGEX + ")");
        String autoCommentAdditional = "[titles joined]";

        EntityJoiner joiner = new EntityJoiner(ent, TITLE_ACADEMIC_REPLACE_FRONT_PART,
                pattern, valueList, autoCommentAdditional);
        joiner.join();

        String actualEnt = joiner.getEnt();
        String expectedEnt = "<<title:1>> <<nn:1>>, <<vn:1>> , Hamburg, *01.02.1983";
        assertEquals(expectedEnt, actualEnt);

        List<String> expectedValueList = CollectionsHelper.buildListFrom("Prof. Dr.");
        assertEquals(expectedValueList, valueList);

        String actualAutoComment = joiner.getAutoComment();
        String expectedAutoComment = " [titles joined]";
        assertEquals(expectedAutoComment, actualAutoComment);
    }

}

