/* BdfServer_Multi - Copyright (c) 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 fr.exemole.bdfserver.multi.jsonproducers.central;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.conf.BdfServerDirs;
import fr.exemole.bdfserver.multi.api.Multi;
import fr.exemole.bdfserver.multi.api.central.CentralSphere;
import fr.exemole.bdfserver.multi.tools.FichothequeInfo;
import fr.exemole.bdfserver.storage.directory.tools.SphereChecker;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import net.fichotheque.FichothequeConstants;
import net.fichotheque.sphere.Redacteur;
import net.fichotheque.sphere.Sphere;
import net.mapeadores.util.json.JSONWriter;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.json.JsonProperty;


/**
 *
 * @author Vincent Calame
 */
public class CentralSphereStatsJsonProperty implements JsonProperty {

    public final static String NOT_HERE = "no";
    public final static String HERE = "here";
    private final Multi multi;
    private final CentralSphere centralSphere;
    private final Lang lang;

    public CentralSphereStatsJsonProperty(Multi multi, CentralSphere centralSphere, Lang lang) {
        this.multi = multi;
        this.centralSphere = centralSphere;
        this.lang = lang;
    }

    @Override
    public String getName() {
        return "stats";
    }

    @Override
    public void writeValue(JSONWriter jw) throws IOException {
        List<StatInfo> statInfoList = scan();
        jw.object();
        {
            jw.key("fichothequeArray");
            jw.array();
            for (StatInfo statInfo : statInfoList) {
                write(jw, statInfo);
            }
            jw.endArray();
        }
        jw.endObject();
    }

    private List<StatInfo> scan() {
        List<StatInfo> statInfoList = new ArrayList<StatInfo>();
        for (String name : multi.getExistingNameSet()) {
            BdfServer bdfServer = multi.getInitBdfServer(name);
            StatInfo statInfo;
            if (bdfServer != null) {
                statInfo = getStatInfo(name, bdfServer);
            } else {
                BdfServerDirs bdfServerDirs = multi.getBdfServerDirs(name);
                statInfo = getStatInfo(name, bdfServerDirs);
            }
            statInfoList.add(statInfo);
        }
        return statInfoList;
    }

    private StatInfo getStatInfo(String name, BdfServer bdfServer) {
        Sphere sphere = (Sphere) bdfServer.getFichotheque().getSubset(centralSphere.getSphereKey());
        if (sphere == null) {
            return new StatInfo(name, bdfServer, false);
        }
        StatInfo statInfo = new StatInfo(name, bdfServer, true);
        for (Redacteur redacteur : sphere.getRedacteurList()) {
            String login = redacteur.getLogin();
            if (!centralSphere.hasCentralUser(login)) {
                statInfo.addOutside(login);
            } else {
                statInfo.checkRedacteur(redacteur);
            }
        }
        return statInfo;
    }

    private StatInfo getStatInfo(String name, BdfServerDirs bdfServerDirs) {
        boolean here = SphereChecker.containsSphere(centralSphere.getSphereKey(), bdfServerDirs);
        return new StatInfo(name, bdfServerDirs, here);
    }

    private void write(JSONWriter jw, StatInfo statInfo) throws IOException {
        jw.object();
        {
            jw.key("fichothequeName")
                    .value(statInfo.getName());
            jw.key("fichothequeTitle")
                    .value(statInfo.getFichothequeTitle(lang));
            jw.key("fichothequeInit")
                    .value(statInfo.isInit());
            jw.key("here")
                    .value(statInfo.isHere());
            jw.key("loginArrays");
            jw.object();
            writeArray(jw, "active", statInfo.activeSet);
            writeArray(jw, "readonly", statInfo.readonlySet);
            writeArray(jw, "inactive", statInfo.inactiveSet);
            writeArray(jw, "outside", statInfo.outsideSet);
            jw.endObject();
        }
        jw.endObject();
    }

    private void writeArray(JSONWriter jw, String key, Collection<String> collection) throws IOException {
        jw.key(key);
        jw.array();
        for (String login : collection) {
            jw.value(login);
        }
        jw.endArray();
    }


    private static class StatInfo extends FichothequeInfo {

        private final boolean here;
        private final SortedSet<String> activeSet = new TreeSet<>();
        private final SortedSet<String> readonlySet = new TreeSet<>();
        private final SortedSet<String> inactiveSet = new TreeSet<>();
        private final SortedSet<String> outsideSet = new TreeSet<>();

        public StatInfo(String name, BdfServer bdfServer, boolean here) {
            super(name, bdfServer);
            this.here = here;
        }

        public StatInfo(String name, BdfServerDirs bdfServerDirs, boolean here) {
            super(name, bdfServerDirs);
            this.here = here;
        }

        public boolean isHere() {
            return here;
        }

        public void addOutside(String login) {
            outsideSet.add(login);
        }

        public void checkRedacteur(Redacteur redacteur) {
            String login = redacteur.getLogin();
            switch (redacteur.getStatus()) {
                case FichothequeConstants.INACTIVE_STATUS:
                    inactiveSet.add(login);
                    break;
                case FichothequeConstants.READONLY_STATUS:
                    readonlySet.add(login);
                    break;
                default:
                    activeSet.add(login);
            }
        }

    }

}
