/* UtilLib - Copyright (c) 2014 -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 net.mapeadores.util.json;

import java.io.IOException;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.attr.AttributeKey;
import net.mapeadores.util.attr.Attributes;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.Langs;
import net.mapeadores.util.localisation.Message;
import net.mapeadores.util.localisation.MessageLocalisation;
import net.mapeadores.util.logging.CommandMessage;
import net.mapeadores.util.logging.LineLog;
import net.mapeadores.util.logging.LineMessage;
import net.mapeadores.util.logging.SourceLog;
import net.mapeadores.util.logging.SourceMessage;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.Labels;
import net.mapeadores.util.text.Phrase;
import net.mapeadores.util.text.Phrases;


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

    private CommonJson() {

    }

    public static void array(JSONWriter jw, Langs langs) throws IOException {
        jw.array();
        for (Lang lang : langs) {
            jw.value(lang.toString());
        }
        jw.endArray();
    }

    public static void object(JSONWriter jw, Attributes attributes) throws IOException {
        jw.object();
        properties(jw, attributes);
        jw.endObject();
    }

    public static void properties(JSONWriter jw, Attributes attributes) throws IOException {
        for (Attribute attribute : attributes) {
            AttributeKey attributeKey = attribute.getAttributeKey();
            jw.key(attributeKey.toString());
            jw.array();
            for (String value : attribute) {
                jw.value(value);
            }
            jw.endArray();
        }
    }

    public static void object(JSONWriter jw, Labels labels) throws IOException {
        jw.object();
        properties(jw, labels);
        jw.endObject();
    }

    public static void properties(JSONWriter jw, Labels labels) throws IOException {
        for (Label label : labels) {
            jw.key(label.getLang().toString());
            jw.value(label.getLabelString());
        }
    }

    public static void object(JSONWriter jw, CommandMessage commandMessage, MessageLocalisation messageLocalisation) throws IOException {
        jw.object();
        properties(jw, commandMessage, messageLocalisation);
        jw.endObject();
    }

    public static void properties(JSONWriter jw, CommandMessage commandMessage, MessageLocalisation messageLocalisation) throws IOException {
        jw.key("type");
        if (commandMessage.isErrorMessage()) {
            jw.value("error");
        } else {
            jw.value("done");
        }
        jw.key("key")
                .value(commandMessage.getMessageKey());
        jw.key("values");
        jw.array();
        for (Object value : commandMessage.getMessageValues()) {
            jw.value(value);
        }
        jw.endArray();
        if (messageLocalisation != null) {
            jw.key("text")
                    .value(messageLocalisation.toString(commandMessage));
        }
        if (commandMessage.hasCommandLogs()) {
            jw.key("logs");
            jw.array();
            for (SourceLog sourceLog : commandMessage.getCommandLogs()) {
                jw.object();
                properties(jw, sourceLog, messageLocalisation);
                jw.endObject();
            }
            jw.endArray();
        }
        if (commandMessage.hasMultiError()) {
            jw.key("multiErrorMessageArray");
            jw.array();
            for (Message multiErrorMessage : commandMessage.getMultiErrorList()) {
                jw.object();
                {
                    jw.key("key")
                            .value(multiErrorMessage.getMessageKey());
                    jw.key("values");
                    jw.array();
                    for (Object value : commandMessage.getMessageValues()) {
                        jw.value(value);
                    }
                    jw.endArray();
                    if (multiErrorMessage instanceof LineMessage) {
                        jw.key("line")
                                .value(((LineMessage) multiErrorMessage).getLineNumber());
                    }
                    if (messageLocalisation != null) {
                        jw.key("text")
                                .value(messageLocalisation.toString(multiErrorMessage));
                    }
                }
                jw.endObject();
            }
            jw.endArray();
        }
    }

    public static void object(JSONWriter jw, Message message, MessageLocalisation messageLocalisation) throws IOException {
        jw.object();
        properties(jw, message, messageLocalisation);
        jw.endObject();
    }

    public static void properties(JSONWriter jw, Message message, MessageLocalisation messageLocalisation) throws IOException {
        if (message instanceof CommandMessage) {
            properties(jw, (CommandMessage) message, messageLocalisation);
            return;
        }
        jw.key("key")
                .value(message.getMessageKey());
        jw.key("text")
                .value(messageLocalisation.toString(message));
        Object[] values = message.getMessageValues();
        if (values.length > 0) {
            jw.key("valueArray");
            jw.array();
            for (Object value : values) {
                jw.value(value);
            }
            jw.endArray();
        }
    }

    public static void properties(JSONWriter jw, SourceLog sourceLog, MessageLocalisation messageLocalisation) throws IOException {
        jw.key("name")
                .value(sourceLog.getName());
        jw.key("messageArray");
        jw.array();
        for (SourceMessage sourceMessage : sourceLog.getSourceMessageList()) {
            jw.object();
            jw.key("category")
                    .value(sourceMessage.getCategory());
            properties(jw, sourceMessage, messageLocalisation);
            jw.endObject();
        }
        jw.endArray();
    }


    public static void properties(JSONWriter jw, LineLog lineLog, MessageLocalisation messageLocalisation) throws IOException {
        jw.key("line")
                .value(lineLog.getLineNumber());
        jw.key("messageArray");
        jw.array();
        for (LineMessage lineMessage : lineLog.getLineMessageList()) {
            jw.object();
            jw.key("category")
                    .value(lineMessage.getCategory());
            properties(jw, lineMessage, messageLocalisation);
            jw.endObject();
        }
        jw.endArray();
    }

    public static void title(JSONWriter jw, Labels labels, Lang lang) throws IOException {
        jw.key("title");
        Label label = labels.getLangPartCheckedLabel(lang);
        if (label != null) {
            jw.value(label.getLabelString());
        } else {
            jw.value("");
        }
    }

    public static void defaultLabel(JSONWriter jw, Labels labels, Lang lang, String key, String defaultString) throws IOException {
        String value = labels.seekLabelString(lang, defaultString);
        if (value != null) {
            jw.key(key);
            jw.value(value);
        }
    }

    public static void object(JSONWriter jw, Phrases phrases) throws IOException {
        jw.object();
        properties(jw, phrases);
        jw.endObject();
    }

    public static void properties(JSONWriter jw, Phrases phrases) throws IOException {
        for (Phrase phrase : phrases) {
            jw.key(phrase.getName());
            object(jw, (Labels) phrase);
        }
    }


    public static void object(JSONWriter jw, Phrases phrases, Lang lang) throws IOException {
        jw.object();
        properties(jw, phrases, lang);
        jw.endObject();
    }

    public static void properties(JSONWriter jw, Phrases phrases, Lang lang) throws IOException {
        for (Phrase phrase : phrases) {
            defaultLabel(jw, phrase, lang, phrase.getName(), null);
        }
    }

}
