/* FichothequeLib_Tools - Copyright (c) 2013-2022 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.extraction.corpus;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.croisement.Croisement;
import net.fichotheque.extraction.def.FicheFilter;
import net.fichotheque.extraction.def.GroupClause;
import net.fichotheque.extraction.def.TagNameInfo;
import net.fichotheque.extraction.run.FicheExtractInfo;
import net.fichotheque.extraction.run.FicheGroup;
import net.mapeadores.util.exceptions.SwitchException;
import net.mapeadores.util.text.collation.group.CollationGroup;
import net.mapeadores.util.text.collation.group.CollationGroupBuilder;
import net.mapeadores.util.text.collation.group.ObjectWrapper;


/**
 *
 * @author Vincent Calame
 */
public abstract class GroupEngine {

    GroupEngine() {
    }

    public static GroupEngine newInstance(GroupClause groupClause) {
        if (groupClause == null) {
            return new PositionEngine(null, null);
        }
        GroupEngineProvider groupEngineProvider = GroupEngineProvider.newInstance(groupClause);
        return groupEngineProvider.newGroupEngine();

    }

    public abstract void add(FicheMeta ficheMeta, FicheFilter ficheFilter, Croisement croisement);

    public abstract FicheGroup[] toFicheGroupArray();

    public String getTagName(GroupClause groupClause) {
        TagNameInfo tagNameInfo = groupClause.getTagNameInfo();
        switch (tagNameInfo.getType()) {
            case TagNameInfo.CUSTOM_TYPE:
                return tagNameInfo.getCustomTagName();
            case TagNameInfo.NULL_TYPE:
                return null;
            default:
                return "group";
        }
    }

    static FicheGroup[] toGroupArray(Collection<GroupBuilder> sortedCollection, GroupClause groupClause, GroupBuilder outsideCollectionGroupeBuilder) {
        boolean asc = true;
        if (groupClause != null) {
            asc = (groupClause.isAscendingOrder());
        }
        int size = sortedCollection.size();
        int p = (asc) ? 0 : (size - 1);
        FicheGroup[] result;
        if (outsideCollectionGroupeBuilder != null) {
            result = new FicheGroup[size + 1];
            result[size] = outsideCollectionGroupeBuilder.toFicheGroup();
        } else {
            result = new FicheGroup[size];
        }
        for (GroupBuilder groupBuilder : sortedCollection) {
            result[p] = groupBuilder.toFicheGroup();
            if (asc) {
                p++;
            } else {
                p--;
            }
        }
        return result;
    }

    static FicheGroup[] toGroupArray(CollationGroupBuilder collationGroupBuilder, GroupClause groupClause, GroupEngineProvider subEngineProvider) {
        boolean asc = (groupClause.isAscendingOrder());
        List list = collationGroupBuilder.getCollationGroupList();
        int size = list.size();
        List<GroupBuilder> groupBuilderList = new ArrayList<GroupBuilder>();
        for (int i = 0; i < size; i++) {
            CollationGroup collationGroup = (CollationGroup) list.get(i);
            char[] array = new char[1];
            array[0] = collationGroup.getInitial();
            String name = new String(array);
            Map<String, String> attributesMap = new HashMap<String, String>();
            int byInteger = getByInteger(array[0]);
            attributesMap.put("order", String.valueOf(byInteger));
            GroupBuilder groupBuilder = GroupBuilder.newInstance(name, groupClause.getTagNameInfo(), subEngineProvider);
            groupBuilder.setAttributesMap(attributesMap);
            List<ObjectWrapper> wrapperList = collationGroup.getSortedObjectWrapperList();
            int wrapperLength = wrapperList.size();
            for (int j = 0; j < wrapperLength; j++) {
                int index;
                if (asc) {
                    index = j;
                } else {
                    index = size - j - 1;
                }
                ObjectWrapper wrapper = wrapperList.get(index);
                FicheExtractInfo ficheExtractInfo = (FicheExtractInfo) wrapper.getObject();
                groupBuilder.add(ficheExtractInfo);
            }
            groupBuilderList.add(groupBuilder);
        }
        return toGroupArray(groupBuilderList, groupClause, null);
    }

    private static int getByInteger(char c) {
        if (c == CollationGroup.NOLETTER_INITIAL) {
            return 10;
        }
        if (c == CollationGroup.NOEUROPEAN_INITIAL) {
            return 37;
        }
        if (c >= '0' && c <= '9') {
            return (int) (c - 48);
        }
        if (c >= 'A' && c <= 'Z') {
            return (int) (c - 54);
        }
        throw new SwitchException("char = " + c);
    }

}
