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

import java.util.SortedMap;
import java.util.TreeMap;
import net.fichotheque.SubsetKey;
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.FicheGroup;
import net.fichotheque.utils.CroisementUtils;


/**
 *
 * @author Vincent Calame
 */
class PositionEngine extends GroupEngine {

    private final SortedMap<PositionSortKey, GroupBuilder> treeMap = new TreeMap<PositionSortKey, GroupBuilder>();
    private final GroupClause groupClause;
    private final GroupEngineProvider subGroupEngineProvider;

    PositionEngine(GroupClause groupClause, GroupEngineProvider subGroupEngineProvider) {
        this.groupClause = groupClause;
        this.subGroupEngineProvider = subGroupEngineProvider;
    }

    @Override
    public void add(FicheMeta ficheMeta, FicheFilter ficheFilter, Croisement croisement) {
        int position = -1;
        if (croisement != null) {
            position = CroisementUtils.getPosition(ficheMeta, croisement.getCroisementKey(), croisement.getLienList().get(0));
        }
        PositionSortKey positionSortKey = new PositionSortKey(ficheMeta.getSubsetKey(), position);
        GroupBuilder groupBuilder = treeMap.get(positionSortKey);
        if (groupBuilder == null) {
            TagNameInfo tagNameInfo = TagNameInfo.NULL;
            if (groupClause != null) {
                tagNameInfo = groupClause.getTagNameInfo();
            }
            groupBuilder = GroupBuilder.newInstance(positionSortKey.toString(), tagNameInfo, subGroupEngineProvider);
            treeMap.put(positionSortKey, groupBuilder);
        }
        groupBuilder.add(ficheMeta, ficheFilter, croisement);
    }

    @Override
    public FicheGroup[] toFicheGroupArray() {
        return toGroupArray(treeMap.values(), groupClause, null);
    }


    private static class PositionSortKey implements Comparable<PositionSortKey> {

        private final SubsetKey subsetKey;
        private final int position;

        private PositionSortKey(SubsetKey subsetKey, int position) {
            this.subsetKey = subsetKey;
            this.position = position;
        }

        @Override
        public int hashCode() {
            return subsetKey.hashCode() * 1000 + position;
        }

        @Override
        public boolean equals(Object other) {
            if (other == null) {
                return false;
            }
            if (other == this) {
                return true;
            }
            if (other.getClass() != this.getClass()) {
                return false;
            }
            PositionSortKey otherPositionSortKey = (PositionSortKey) other;
            return ((otherPositionSortKey.subsetKey.equals(this.subsetKey)) && (otherPositionSortKey.position == this.position));
        }

        @Override
        public String toString() {
            return subsetKey + "/" + position;
        }

        @Override
        public int compareTo(PositionSortKey otherPositionSortKey) {
            int compare = this.subsetKey.compareTo(otherPositionSortKey.subsetKey);
            if (compare != 0) {
                return compare;
            }
            if ((otherPositionSortKey.position < 1) && (this.position >= 1)) {
                return -1;
            } else if ((otherPositionSortKey.position >= 1) && (this.position < 1)) {
                return 1;
            } else if (otherPositionSortKey.position > this.position) {
                return -1;
            } else if (otherPositionSortKey.position < this.position) {
                return 1;
            } else {
                return 0;
            }
        }

    }

}
