/* FichothequeLib_Tools - Copyright (c) 2007-2023 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;

import java.util.List;
import java.util.TreeSet;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.ThesaurusEditor;


/**
 *
 * @author Vincent Calame
 */
public class IdalphaSortEngine {

    private final ThesaurusEditor thesaurusEditor;
    private boolean recursive = false;
    private boolean descending = false;
    private boolean ignoreCase = false;
    private boolean ignorePunctuation = false;

    public IdalphaSortEngine(ThesaurusEditor thesaurusEditor) {
        this.thesaurusEditor = thesaurusEditor;
    }

    public IdalphaSortEngine setRecursive(boolean recursive) {
        this.recursive = recursive;
        return this;
    }

    public IdalphaSortEngine setDescending(boolean descending) {
        this.descending = descending;
        return this;
    }

    public IdalphaSortEngine setIgnoreCase(boolean ignoreCase) {
        this.ignoreCase = ignoreCase;
        return this;
    }

    public IdalphaSortEngine setIgnorePunctuation(boolean ignorePunctuation) {
        this.ignorePunctuation = ignorePunctuation;
        return this;
    }

    public void sort(Motcle motcle) {
        List<Motcle> children = (motcle != null) ? motcle.getChildList() : thesaurusEditor.getThesaurus().getFirstLevelList();
        int size = children.size();
        if (size == 0) {
            return;
        }
        if (size == 1) {
            if (recursive) {
                sort(children.get(0));
            }
            return;
        }
        TreeSet<MotcleBundle> treeSet = new TreeSet<MotcleBundle>();
        for (Motcle child : children) {
            treeSet.add(new MotcleBundle(child));
        }
        int p = (descending) ? (size - 1) : 0;
        for (MotcleBundle motcleBundle : treeSet) {
            Motcle child = motcleBundle.motcle;
            if (child.getChildIndex() != p) {
                thesaurusEditor.setChildIndex(child, p);
            }
            if (descending) {
                p--;
            } else {
                p++;
            }
        }
        if (recursive) {
            for (int i = 0; i < size; i++) {
                sort(children.get(i));
            }
        }
    }

    public static IdalphaSortEngine init(ThesaurusEditor thesaurusEditor) {
        return new IdalphaSortEngine(thesaurusEditor);
    }

    private String charcleanIdalpha(String idalpha) {
        if (ignorePunctuation) {
            int length = idalpha.length();
            StringBuilder buf = new StringBuilder(length);
            for (int i = 0; i < length; i++) {
                char carac = idalpha.charAt(i);
                if (Character.isLetterOrDigit(carac)) {
                    if (ignoreCase) {
                        carac = Character.toUpperCase(carac);
                    }
                    buf.append(carac);
                }
            }
            return buf.toString();
        } else if (ignoreCase) {
            return idalpha.toUpperCase();
        } else {
            return idalpha;
        }
    }

    private String cleanIdalpha(String idalpha) {
        String result = charcleanIdalpha(idalpha);
        try {
            int itg = Integer.parseInt(result);
            if (itg < 0) {
                return result;
            }
            StringBuilder buf = new StringBuilder(16);
            int length = result.length();
            for (int i = 0; i < (11 - length); i++) {
                buf.append('0');
            }
            buf.append(result);
            return buf.toString();
        } catch (NumberFormatException nfe) {
            return result;
        }
    }


    private class MotcleBundle implements Comparable {

        private final String cleanedIdalpha;
        private final String idalpha;
        private final Motcle motcle;

        private MotcleBundle(Motcle motcle) {
            this.motcle = motcle;
            this.idalpha = motcle.getIdalpha();
            this.cleanedIdalpha = cleanIdalpha(idalpha);
        }

        @Override
        public int hashCode() {
            return idalpha.hashCode();
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == this) {
                return true;
            }
            if (!(obj instanceof MotcleBundle)) {
                return false;
            }
            return ((MotcleBundle) obj).idalpha.equals(this.idalpha);
        }

        @Override
        public int compareTo(Object obj) {
            MotcleBundle other = (MotcleBundle) obj;
            int val = cleanedIdalpha.compareTo(other.cleanedIdalpha);
            if (val != 0) {
                return val;
            }
            return idalpha.compareTo(other.idalpha);
        }

    }

}
