/* FichothequeLib_Tools - Copyright (c) 2024 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.fichotheque.tools.thesaurus.sortprecedence;

import java.text.Collator;
import java.text.RuleBasedCollator;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import net.fichotheque.thesaurus.Motcle;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.text.collation.CollationUnit;


/**
 *
 * @author Vincent Calame
 */
public class PrecedenceComparator implements Comparator<Motcle> {

    private final Lang lang;
    private final String originalPrecedence;
    private final String lowPrecedence;
    private final boolean withLowTest;
    private final RuleBasedCollator collator;
    private final String collatedPrecedence;
    private final Map<String, SortKey> keyMap = new HashMap<String, SortKey>();

    public PrecedenceComparator(String originalPrecedence, Lang lang) {
        this.originalPrecedence = originalPrecedence;
        this.lowPrecedence = originalPrecedence.toLowerCase();
        this.withLowTest = (!originalPrecedence.equals(lowPrecedence));
        this.lang = lang;
        this.collator = (RuleBasedCollator) Collator.getInstance(lang.toLocale());
        collator.setStrength(Collator.PRIMARY);
        this.collatedPrecedence = CollationUnit.collate(originalPrecedence, collator);
    }

    @Override
    public int compare(Motcle mc1, Motcle mc2) {
        SortKey sortKey1 = getSortKey(mc1);
        SortKey sortKey2 = getSortKey(mc2);
        return sortKey1.compareTo(sortKey2);
    }

    private SortKey getSortKey(Motcle motcle) {
        String globalId = motcle.getGlobalId();
        SortKey sortKey = keyMap.get(globalId);
        if (sortKey == null) {
            String labelString = motcle.getLabelString(lang, "");
            String collatedLabel;
            if (!labelString.isEmpty()) {
                collatedLabel = CollationUnit.collate(labelString, collator);
            } else {
                collatedLabel = "";
            }
            String idalpha = motcle.getIdalpha();
            int rate = getRate(idalpha, collatedLabel);
            sortKey = new SortKey(rate, globalId, idalpha, collatedLabel);
            keyMap.put(globalId, sortKey);
        }
        return sortKey;
    }

    private int getRate(String idalpha, String collatedLabel) {
        if (idalpha != null) {
            int idalphaRate = getIdalphaRate(idalpha);
            if (idalphaRate > 0) {
                return idalphaRate;
            }
        }
        return getLabelRate(collatedLabel);
    }

    private int getIdalphaRate(String idalpha) {
        String lowIdalpha = idalpha.toLowerCase();
        if (idalpha.equals(originalPrecedence)) {
            return 99;
        }
        if (withLowTest) {
            if (idalpha.equals(lowPrecedence)) {
                return 97;
            }
            if (lowIdalpha.equals(lowPrecedence)) {
                return 95;
            }
        } else {
            if (lowIdalpha.equals(originalPrecedence)) {
                return 96;
            }
        }
        if (idalpha.startsWith(originalPrecedence)) {
            return 89;
        }
        if (withLowTest) {
            if (idalpha.startsWith(lowPrecedence)) {
                return 87;
            }
            if (lowIdalpha.startsWith(lowPrecedence)) {
                return 85;
            }
        } else {
            if (lowIdalpha.startsWith(originalPrecedence)) {
                return 86;
            }
        }
        if (idalpha.contains(originalPrecedence)) {
            return 79;
        }
        if (withLowTest) {
            if (idalpha.contains(lowPrecedence)) {
                return 77;
            }
            if (lowIdalpha.contains(lowPrecedence)) {
                return 75;
            }
        } else {
            if (lowIdalpha.contains(originalPrecedence)) {
                return 76;
            }
        }
        return 0;
    }

    private int getLabelRate(String collatedLabel) {
        if (collatedLabel.equals(collatedPrecedence)) {
            return 69;
        }
        int index = collatedLabel.indexOf(collatedPrecedence);
        if (index == 0) {
            return 67;
        }
        if (index > 0) {
            if (index < 12) {
                return 65;
            } else {
                return 63;
            }
        }
        return 0;
    }


    private static class SortKey {

        private final int rate;
        private final String idalpha;
        private final String globalId;
        private final String collatedLabel;

        private SortKey(int rate, String globalId, String idalpha, String collatedLabel) {
            this.rate = rate;
            this.globalId = globalId;
            this.idalpha = idalpha;
            this.collatedLabel = collatedLabel;
        }

        private int compareTo(SortKey otherKey) {
            if (this.rate > otherKey.rate) {
                return -1;
            }
            if (this.rate < otherKey.rate) {
                return 1;
            }
            if (this.idalpha != null) {
                if (otherKey.idalpha == null) {
                    return -1;
                } else {
                    int comp = this.idalpha.compareTo(otherKey.idalpha);
                    if (comp != 0) {
                        return comp;
                    }
                }
            } else if (otherKey.idalpha != null) {
                return 1;
            }
            int comp = this.collatedLabel.compareTo(otherKey.collatedLabel);
            if (comp != 0) {
                return comp;
            }
            return this.globalId.compareTo(otherKey.globalId);
        }

    }

}
