/* BdfServer - 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 fr.exemole.bdfserver.tools;

import fr.exemole.bdfserver.tools.storage.StorageUtils;
import java.io.IOException;
import java.io.Reader;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import net.mapeadores.util.exceptions.NestedIOException;
import net.mapeadores.util.ini.IniParser;
import net.mapeadores.util.io.DocStream;
import net.mapeadores.util.io.ResourceFolder;
import net.mapeadores.util.io.ResourceStorage;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.MessageLocalisationFactory;
import net.mapeadores.util.text.RelativePath;


/**
 *
 * @author Vincent Calame
 */
public class BdfMessageLocalisationFactory extends MessageLocalisationFactory {

    private final static RelativePath CORE_PATH = RelativePath.build("l10n");
    private final static RelativePath CUSTOM_PATH = RelativePath.build("custom/l10n");

    private BdfMessageLocalisationFactory() {

    }

    private void scan(ResourceStorage resourceStorage) {
        scanAddonFolder(resourceStorage, StorageUtils.APPS_ROOT);
        scanAddonFolder(resourceStorage, StorageUtils.EXTENSION_RESOURCE_ROOT);
        ResourceFolder coreFolder = resourceStorage.getResourceFolder(CORE_PATH);
        if (coreFolder != null) {
            scanL10nFolder(resourceStorage, coreFolder, CORE_PATH);
        }
    }

    private void scanAddonFolder(ResourceStorage resourceStorage, RelativePath rootPath) {
        ResourceFolder rootFolder = resourceStorage.getResourceFolder(rootPath);
        if (rootFolder != null) {
            for (ResourceFolder subfolder1 : rootFolder.getSubfolderList()) {
                RelativePath subpath1 = rootPath.buildChild(subfolder1.getName());
                for (ResourceFolder subfolder2 : subfolder1.getSubfolderList()) {
                    if (subfolder2.getName().equals("l10n")) {
                        scanL10nFolder(resourceStorage, subfolder2, subpath1.buildChild(subfolder2.getName()));
                    }
                }
            }
        }
    }


    private void scanCustom(ResourceStorage resourceStorage) {
        ResourceFolder customFolder = resourceStorage.getResourceFolder(CUSTOM_PATH);
        if (customFolder != null) {
            for (String resourceName : customFolder.getResourceNameList()) {
                if (resourceName.endsWith(".ini")) {
                    try {
                        Lang lang = Lang.parse(resourceName.substring(0, resourceName.length() - 4));
                        loadIni(resourceStorage, lang, CUSTOM_PATH.buildChild(resourceName));
                    } catch (ParseException pe) {

                    }
                }
            }
        }

    }

    private void scanL10nFolder(ResourceStorage resourceStorage, ResourceFolder l10nFolder, RelativePath l10nPath) {
        for (ResourceFolder langFolder : l10nFolder.getSubfolderList()) {
            try {
                Lang lang = Lang.parse(langFolder.getName());
                scanLangFolder(resourceStorage, lang, langFolder, l10nPath.buildChild(langFolder.getName()));
            } catch (ParseException pe) {

            }
        }
        for (String resourceName : l10nFolder.getResourceNameList()) {
            if (resourceName.endsWith(".ini")) {
                try {
                    Lang lang = Lang.parse(resourceName.substring(0, resourceName.length() - 4));
                    loadIni(resourceStorage, lang, l10nPath.buildChild(resourceName));
                } catch (ParseException pe) {

                }
            }
        }
    }

    private void scanLangFolder(ResourceStorage resourceStorage, Lang lang, ResourceFolder langFolder, RelativePath langPath) {
        SortedMap<String, RelativePath> pathMap = new TreeMap<String, RelativePath>();
        for (String resourceName : langFolder.getResourceNameList()) {
            if (resourceName.endsWith(".ini")) {
                pathMap.put(resourceName, langPath.buildChild(resourceName));
            }
        }
        for (RelativePath relativePath : pathMap.values()) {
            loadIni(resourceStorage, lang, relativePath);
        }
    }

    private void loadIni(ResourceStorage resourceStorage, Lang lang, RelativePath relativePath) {
        DocStream docStream = resourceStorage.getResourceDocStream(relativePath);
        try (Reader reader = docStream.getReader()) {
            Map<String, String> stringMap = new HashMap<String, String>();
            IniParser.parseIni(reader, stringMap);
            for (Map.Entry<String, String> entry : stringMap.entrySet()) {
                addEntry(entry.getKey(), lang, entry.getValue());
            }
        } catch (IOException ioe) {
            throw new NestedIOException(ioe);
        }
    }

    public static BdfMessageLocalisationFactory buildFactory(List<ResourceStorage> resourceStorageList) {
        BdfMessageLocalisationFactory messageLocalisationFactory = new BdfMessageLocalisationFactory();
        for (ResourceStorage resourceStorage : resourceStorageList) {
            messageLocalisationFactory.scanCustom(resourceStorage);
        }
        for (ResourceStorage resourceStorage : resourceStorageList) {
            messageLocalisationFactory.scan(resourceStorage);
        }
        return messageLocalisationFactory;
    }

}
