/* BdfServer_JsonProducers - Copyright (c) 2013-2021 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 fr.exemole.bdfserver.jsonproducers.addenda;

import fr.exemole.bdfserver.api.BdfServer;
import net.fichotheque.permission.PermissionEntry;
import net.fichotheque.permission.PermissionSummary;
import fr.exemole.bdfserver.api.users.BdfUser;
import net.fichotheque.tools.permission.ListFilterEngine;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.fichotheque.Fichotheque;
import net.fichotheque.SubsetKey;
import net.fichotheque.addenda.Addenda;
import net.fichotheque.addenda.Document;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.croisement.Croisements;
import net.fichotheque.json.DocumentJson;
import net.fichotheque.utils.CorpusMetadataUtils;
import net.fichotheque.utils.FichothequeUtils;
import net.mapeadores.util.json.JSONWriter;
import net.mapeadores.util.json.JsonProducer;
import net.mapeadores.util.json.JsonUtils;
import fr.exemole.bdfserver.api.instruction.BdfParameters;


/**
 *
 * @author Vincent Calame
 */
public class DocumentArrayJsonProducer implements JsonProducer {

    private final BdfServer bdfServer;
    private final BdfUser bdfUser;
    private final Addenda addenda;
    private final PermissionSummary permissionSummary;
    private final List<PermissionEntry> permissionEntryList;

    public DocumentArrayJsonProducer(BdfParameters bdfParameters, Addenda addenda) {
        this.bdfServer = bdfParameters.getBdfServer();
        this.bdfUser = bdfParameters.getBdfUser();
        this.addenda = addenda;
        this.permissionSummary = bdfParameters.getPermissionSummary();
        this.permissionEntryList = ListFilterEngine.filter(addenda, addenda.getSubsetItemList(), permissionSummary);
    }

    @Override
    public void writeJson(Appendable appendable) throws IOException {
        JSONWriter jw = new JSONWriter(appendable);
        Fichotheque fichotheque = bdfServer.getFichotheque();
        Corpus[] corpusArray = FichothequeUtils.toCorpusArray(bdfServer.getFichotheque(), permissionSummary.getSubsetAccessPredicate());
        int corpusCount = corpusArray.length;
        Map<Integer, FicheMeta>[] mapArray = new Map[corpusCount];
        for (int i = 0; i < corpusCount; i++) {
            mapArray[i] = new HashMap<Integer, FicheMeta>();
        }
        jw.object();
        {
            jw.key("documentArray");
            jw.array();
            for (PermissionEntry permissionEntry : permissionEntryList) {
                Document document = (Document) permissionEntry.getSubsetItem();
                boolean editable = permissionEntry.isEditable();
                jw.object();
                {
                    DocumentJson.properties(jw, document, bdfUser, JsonUtils.ALL_ELIGIBILITY);
                    jw.key("editable")
                            .value(editable);
                    int ficheCount = 0;
                    if (corpusCount > 0) {
                        boolean here = false;
                        for (int j = 0; j < corpusCount; j++) {
                            Corpus corpus = corpusArray[j];
                            Croisements ficheCroisements = fichotheque.getCroisements(document, corpus);
                            if (!ficheCroisements.isEmpty()) {
                                if (!here) {
                                    here = true;
                                    jw.key("corpusMap");
                                    jw.object();
                                }
                                Map<Integer, FicheMeta> map = mapArray[j];
                                SubsetKey corpusKey = corpus.getSubsetKey();
                                jw.key(corpusKey.getSubsetName());
                                jw.array();
                                for (Croisements.Entry entry : ficheCroisements.getEntryList()) {
                                    FicheMeta ficheMeta = (FicheMeta) entry.getSubsetItem();
                                    jw.value(ficheMeta.getId());
                                    ficheCount++;
                                    map.put(ficheMeta.getId(), ficheMeta);
                                }
                                jw.endArray();
                            }
                        }
                        if (here) {
                            jw.endObject();
                        }
                    }
                    jw.key("ficheCount")
                            .value(ficheCount);
                }
                jw.endObject();
            }
            jw.endArray();
            jw.key("corpusMap");
            jw.object();
            for (int i = 0; i < corpusCount; i++) {
                Map<Integer, FicheMeta> map = mapArray[i];
                if (!map.isEmpty()) {
                    jw.key(corpusArray[i].getSubsetName());
                    jw.object();
                    for (FicheMeta ficheMeta : map.values()) {
                        jw.key(String.valueOf(ficheMeta.getId()));
                        jw.object();
                        {
                            jw.key("title")
                                    .value(CorpusMetadataUtils.getFicheTitle(ficheMeta, bdfUser.getWorkingLang(), bdfUser.getFormatLocale()));
                        }
                        jw.endObject();
                    }
                    jw.endObject();
                }
            }
            jw.endObject();
        }
        jw.endObject();
    }

}
