/* FichothequeLib_Tools - Copyright (c) 2013-2017 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.List;
import java.util.Map;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.corpus.fiche.FicheItem;
import net.fichotheque.extraction.def.FicheFilter;
import net.fichotheque.extraction.def.TagNameInfo;
import net.fichotheque.extraction.run.FicheExtractInfo;
import net.fichotheque.extraction.run.FicheGroup;
import net.fichotheque.junction.Junction;


/**
 *
 * @author Vincent Calame
 */
class GroupBuilder {

    private final GroupEngine subGroupEngine;
    private final String name;
    private final TagNameInfo tagNameInfo;
    private List<FicheExtractInfo> infoList;
    private FicheItem[] matchingFicheItemArray;
    private Map<String, String> attributesMap;

    GroupBuilder(String name, TagNameInfo tagNameInfo, GroupEngine subGroupEngine) {
        this.subGroupEngine = subGroupEngine;
        this.name = name;
        this.tagNameInfo = tagNameInfo;
        if (subGroupEngine == null) {
            infoList = new ArrayList<FicheExtractInfo>();
        }
    }

    void add(FicheMeta ficheMeta, FicheFilter ficheFilter, Junction junction) {
        if (subGroupEngine != null) {
            subGroupEngine.add(ficheMeta, ficheFilter, junction);
        } else {
            InternalFicheExtractInfo info = new InternalFicheExtractInfo(ficheMeta, ficheFilter, junction, null);
            infoList.add(info);
        }
    }

    void add(FicheExtractInfo ficheExtractInfo) {
        if (subGroupEngine != null) {
            subGroupEngine.add(ficheExtractInfo.getFicheMeta(), ficheExtractInfo.getFicheFilter(), ficheExtractInfo.getJunction());
        } else {
            infoList.add(ficheExtractInfo);
        }
    }

    void setMatchingFicheItemArray(FicheItem[] matchingFicheItemArray) {
        this.matchingFicheItemArray = matchingFicheItemArray;
    }

    void setAttributesMap(Map<String, String> attributesMap) {
        this.attributesMap = attributesMap;
    }

    FicheGroup toFicheGroup() {
        InternalFicheGroup ficheGroup = new InternalFicheGroup(name, tagNameInfo);
        if (subGroupEngine == null) {
            ficheGroup.bottomGroup = true;
            ficheGroup.subGroupArray = null;
            ficheGroup.ficheExtractInfoArray = infoList.toArray(new FicheExtractInfo[infoList.size()]);
        } else {
            ficheGroup.bottomGroup = false;
            ficheGroup.subGroupArray = subGroupEngine.toFicheGroupArray();
            ficheGroup.ficheExtractInfoArray = null;
        }
        ficheGroup.matchingFicheItemArray = matchingFicheItemArray;
        ficheGroup.attributesMap = attributesMap;
        return ficheGroup;
    }

    static GroupBuilder newInstance(String name, TagNameInfo tagNameInfo, GroupEngineProvider subProvider) {
        GroupEngine subGroupEngine = null;
        if (subProvider != null) {
            subGroupEngine = subProvider.newGroupEngine();
        }
        return new GroupBuilder(name, tagNameInfo, subGroupEngine);
    }

    static FicheExtractInfo toFicheExtractInfo(FicheMeta ficheMeta, FicheFilter ficheFilter, Junction junction, Object groupClauseObject) {
        return new InternalFicheExtractInfo(ficheMeta, ficheFilter, junction, groupClauseObject);
    }


    private static class InternalFicheGroup implements FicheGroup {

        private final String name;
        private final TagNameInfo tagNameInfo;
        private boolean bottomGroup;
        private FicheGroup[] subGroupArray;
        private FicheExtractInfo[] ficheExtractInfoArray;
        private FicheItem[] matchingFicheItemArray;
        private Map<String, String> attributesMap;

        private InternalFicheGroup(String name, TagNameInfo tagNameInfo) {
            this.name = name;
            this.tagNameInfo = tagNameInfo;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public TagNameInfo getTagNameInfo() {
            return tagNameInfo;
        }

        @Override
        public FicheItem[] getMatchingFicheItemArray() {
            return matchingFicheItemArray;
        }

        @Override
        public Map<String, String> getAttributesMap() {
            return attributesMap;
        }

        @Override
        public boolean isBottomGroup() {
            return bottomGroup;
        }

        @Override
        public FicheGroup[] getSubgroupArray() {
            return subGroupArray;
        }

        @Override
        public FicheExtractInfo[] getFicheExtractInfoArray() {
            return ficheExtractInfoArray;
        }

    }


    private static class InternalFicheExtractInfo implements FicheExtractInfo {

        private final FicheFilter ficheFilter;
        private final FicheMeta ficheMeta;
        private final Junction junction;
        private final Object groupClauseObject;

        public InternalFicheExtractInfo(FicheMeta ficheMeta, FicheFilter ficheFilter, Junction junction, Object groupClauseObject) {
            this.ficheFilter = ficheFilter;
            this.ficheMeta = ficheMeta;
            this.junction = junction;
            this.groupClauseObject = groupClauseObject;
        }

        @Override
        public FicheFilter getFicheFilter() {
            return ficheFilter;
        }

        @Override
        public FicheMeta getFicheMeta() {
            return ficheMeta;
        }

        @Override
        public Junction getJunction() {
            return junction;
        }

        @Override
        public Object getGroupClauseObject() {
            return groupClauseObject;
        }

    }

}
