/* BdfServer - Copyright (c) 2019-2025 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.json;

import java.io.IOException;
import java.util.List;
import net.fichotheque.exportation.balayage.BalayageContentDescription;
import net.fichotheque.exportation.balayage.BalayageDef;
import net.fichotheque.exportation.balayage.BalayageDescription;
import net.fichotheque.exportation.balayage.BalayagePostscriptum;
import net.fichotheque.exportation.balayage.BalayageUnit;
import net.fichotheque.xml.defs.BalayageDefXMLPart;
import net.mapeadores.util.exceptions.SwitchException;
import net.mapeadores.util.json.CommonJson;
import net.mapeadores.util.json.JSONWriter;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.MessageLocalisation;
import net.mapeadores.util.logging.LineLog;
import net.mapeadores.util.xml.XMLUtils;


/**
 *
 * @author Vincent Calame
 */
public final class BalayageJson {

    private BalayageJson() {

    }

    public static void properties(JSONWriter jw, BalayageDescription balayageDescription, MessageLocalisation messageLocalisation) throws IOException {
        BalayageDef balayageDef = balayageDescription.getBalayageDef();
        jw.key("name")
                .value(balayageDescription.getName());
        jw.key("state")
                .value(balayageDescription.getState());
        jw.key("labelMap");
        CommonJson.object(jw, balayageDef.getTitleLabels());
        jw.key("attrMap");
        CommonJson.object(jw, balayageDef.getAttributes());
        jw.key("langs");
        jw.array();
        for (Lang lang : balayageDef.getLangs()) {
            jw.value(lang.toString());
        }
        jw.endArray();
        jw.key("targetName")
                .value(balayageDef.getTargetName());
        jw.key("targetPath")
                .value(balayageDef.getTargetPath().toString());
        jw.key("defaultLangOption")
                .value(balayageDef.getDefaultLangOption());
        jw.key("ignoreTransformation")
                .value(balayageDef.ignoreTransformation());
        SelectionOptionsJson.properties(jw, balayageDef.getSelectionOptions());
        postscriptum(jw, balayageDef.getPostscriptum());
        jw.key("units");
        jw.array();
        for (BalayageUnit balayageUnit : balayageDef.getBalayageUnitList()) {
            balayageUnitObject(jw, balayageUnit);
        }
        jw.endArray();
        contentArray(jw, balayageDescription, "", messageLocalisation);
        contentArray(jw, balayageDescription, "extraction", messageLocalisation);
        contentArray(jw, balayageDescription, "xslt", messageLocalisation);
    }

    private static void postscriptum(JSONWriter jw, BalayagePostscriptum postscriptum) throws IOException {
        jw.key("postscriptum");
        jw.object();
        list(jw, "script", postscriptum.getExternalScriptNameList());
        list(jw, "scrutari", postscriptum.getScrutariExportNameList());
        list(jw, "sql", postscriptum.getSqlExportNameList());
        jw.endObject();
    }

    private static void balayageUnitObject(JSONWriter jw, BalayageUnit balayageUnit) throws IOException {
        StringBuilder buf = new StringBuilder();
        BalayageDefXMLPart.init(XMLUtils.toXMLWriter(buf))
                .addBalayageUnit(balayageUnit);
        jw.object();
        jw.key("type")
                .value(balayageUnit.getType());
        jw.key("xml")
                .value(buf.toString());
        jw.endObject();
    }

    private static void list(JSONWriter jw, String key, List<String> list) throws IOException {
        jw.key(key);
        jw.array();
        for (String value : list) {
            jw.value(value);
        }
        jw.endArray();
    }

    private static void contentArray(JSONWriter jw, BalayageDescription balayageDescription, String subDir, MessageLocalisation messageLocalisation) throws IOException {
        List<BalayageContentDescription> list = balayageDescription.getBalayageContentDescriptionList(subDir);
        if (subDir.isEmpty()) {
            jw.key("_core");
        } else {
            jw.key(subDir);
        }
        String state = BalayageDescription.OK_STATE;
        for (BalayageContentDescription contentDescription : list) {
            if (contentDescription.getState() != BalayageContentDescription.OK_STATE) {
                state = BalayageDescription.CONTAINS_ERRORS_STATE;
                break;
            }
        }
        jw.object();
        {
            jw.key("state")
                    .value(state);
            jw.key("array");
            jw.array();
            for (BalayageContentDescription contentDescription : list) {
                String path = contentDescription.getPath();
                int idx = path.lastIndexOf("/");
                String name;
                if (idx == -1) {
                    name = path;
                } else {
                    name = path.substring(idx + 1);
                }
                jw.object();
                {
                    jw.key("name")
                            .value(name);
                    jw.key("path")
                            .value(path);
                    stateAndMessagesProperties(jw, contentDescription, messageLocalisation);
                }
                jw.endObject();
            }
            jw.endArray();
        }
        jw.endObject();
    }

    public static void stateAndMessagesProperties(JSONWriter jw, BalayageContentDescription balayageContentDescription, MessageLocalisation messageLocalisation) throws IOException {
        jw.key("state")
                .value(contentStateToString(balayageContentDescription.getState()));
        jw.key("lineLogArray");
        jw.array();
        for (LineLog lineLog : balayageContentDescription.getLineLogs()) {
            jw.object();
            CommonJson.properties(jw, lineLog, messageLocalisation);
            jw.endObject();
        }
        jw.endArray();
    }

    public static String contentStateToString(short state) {
        switch (state) {
            case BalayageContentDescription.OK_STATE:
                return "ok";
            case BalayageContentDescription.XML_ERROR_STATE:
                return "xml_error";
            default:
                throw new SwitchException("Unknown content state: " + state);
        }
    }

}
