/* FichothequeLib_API - Copyright (c) 2018-2026 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.json;

import java.io.IOException;
import net.fichotheque.SubsetItem;
import net.fichotheque.exportation.table.Cell;
import net.fichotheque.exportation.table.CellConverter;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.date.FuzzyDate;
import net.mapeadores.util.format.FormatConstants;
import net.mapeadores.util.json.JSONString;
import net.mapeadores.util.json.JSONWriter;
import net.mapeadores.util.localisation.LangContext;
import net.mapeadores.util.money.Amount;
import net.mapeadores.util.primitives.Decimal;


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

    private CellJson() {

    }

    public static void value(JSONWriter jw, String formatCast, Object obj, LangContext langContext) throws IOException {
        switch (formatCast) {
            case FormatConstants.INTEGER_CAST:
                jw.value((Long) obj);
                break;
            case FormatConstants.DECIMAL_CAST:
                jw.object();
                 {
                    Decimal decimal = (Decimal) obj;
                    jw.key("type")
                            .value("number");
                    jw.key("code")
                            .value(decimal.toString());
                    jw.key("value")
                            .value(decimal);
                    if (langContext != null) {
                        jw.key("labels");
                        FicheItemJson.decimalLabelsObject(jw, decimal, langContext, "");
                    }
                }
                jw.endObject();
                break;
            case FormatConstants.DATE_CAST:
                jw.object();
                 {
                    FuzzyDate fuzzyDate = (FuzzyDate) obj;
                    jw.key("type")
                            .value("date");
                    jw.key("datetype")
                            .value(fuzzyDate.getDateType());
                    jw.key("code")
                            .value(fuzzyDate.toString());
                    jw.key("iso")
                            .value(fuzzyDate.toISOString(false));
                }
                jw.endObject();
                break;
            case FormatConstants.MONEY_CAST: {
                jw.object();
                {
                    Amount amount = (Amount) obj;
                    Decimal decimal = amount.toDecimal(true);
                    jw.key("type")
                            .value("amount");
                    jw.key("currency")
                            .value(amount.getCurrencyCode());
                    jw.key("decimal")
                            .value(decimal.toString());
                    jw.key("long")
                            .value(amount.getMoneyLong());
                    if (langContext != null) {
                        jw.key("labels");
                        FicheItemJson.amountLabelsObject(jw, decimal, amount.getCurrency(), langContext);
                    }
                }
                jw.endObject();
                break;
            }
            case FormatConstants.PERCENTAGE_CAST:
                jw.object();
                 {
                    Decimal decimal = (Decimal) obj;
                    jw.key("type")
                            .value("percentage");
                    jw.key("code")
                            .value(decimal.toString());
                    jw.key("value")
                            .value(decimal);
                    if (langContext != null) {
                        jw.key("labels");
                        FicheItemJson.decimalLabelsObject(jw, decimal, langContext, "%");
                    }
                }
                jw.endObject();
                break;
            case FormatConstants.JSON_CAST:
                jw.value(new InternalJSONString((String) obj));
                break;
            default:
                jw.value((String) obj);
        }
    }

    public static void cellArrayMappingProperty(JSONWriter jw, SubsetItem subsetItem, CellConverter cellConverter) throws IOException {
        cellArrayMappingProperty(jw, cellConverter.toCellArray(subsetItem), "properties");
    }

    public static void cellArrayMappingProperty(JSONWriter jw, @Nullable Cell[] cellArray) throws IOException {
        cellArrayMappingProperty(jw, cellArray, "properties");
    }

    public static void cellArrayMappingProperty(JSONWriter jw, @Nullable Cell[] cellArray, String propertyKey) throws IOException {
        jw.key(propertyKey);
        jw.object();
        if (cellArray != null) {
            for (Cell cell : cellArray) {
                Object obj = cell.getValue();
                if (obj != null) {
                    jw.key(cell.getColDef().getColName());
                    value(jw, cell.getFormatCast(), obj, cell.getLangContext());
                }
            }
        }
        jw.endObject();
    }


    private static class InternalJSONString implements JSONString {

        private final String jsonString;

        private InternalJSONString(String jsonString) {
            this.jsonString = jsonString;
        }

        @Override
        public String toJSONString() {
            return jsonString;
        }

    }

}
