/* BdfServer_Html - Copyright (c) 2022 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.html;

import fr.exemole.bdfserver.api.BdfExtensionReference;
import fr.exemole.bdfserver.api.managers.ExtensionManager;
import fr.exemole.bdfserver.html.jslib.JsLibCatalog;
import fr.exemole.bdfserver.tools.apps.AppConf;
import fr.exemole.bdfserver.tools.jslib.AppJsLibFactory;
import fr.exemole.bdfserver.tools.jslib.BdfJsLibBuilder;
import fr.exemole.bdfserver.tools.storage.StorageUtils;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.io.ResourceFolder;
import net.mapeadores.util.io.ResourceStorage;
import net.mapeadores.util.io.ResourceStorages;
import net.mapeadores.util.jslib.JsLib;
import net.mapeadores.util.text.RelativePath;


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

    private final BdfHtmlProducer htmlProducer;
    private final AppConf appConf;
    private final String appName;
    private final ResourceStorages resourceStorages;
    private final ExtensionManager extensionManager;


    private AppInit(BdfHtmlProducer htmProducer, AppConf appConf, ResourceStorages resourceStorages, ExtensionManager extensionManager) {
        this.htmlProducer = htmProducer;
        this.appConf = appConf;
        this.appName = appConf.getAppName();
        this.resourceStorages = resourceStorages;
        this.extensionManager = extensionManager;
    }

    private void run() {
        htmlProducer.setWithJavascript(true);
        if (appConf.getBoolean(AppConf.CORE_INCLUDEFICHECSS)) {
            htmlProducer.addFicheCss(false);
        }
        JsLib thirdLibs = getThirdLibs();
        if (thirdLibs != null) {
            htmlProducer.addJsLib(thirdLibs);
        }
        for (String jslibName : appConf.getArray(AppConf.CORE_JSLIBS)) {
            int idx = jslibName.indexOf(":");
            if (idx == -1) {
                JsLib jsLib = JsLibCatalog.CORE.getJsLib(jslibName);
                if (jsLib != null) {
                    htmlProducer.addJsLib(jsLib);
                } else {
                    htmlProducer.addLog("[core_jslibs] Unknown jsLib: " + jslibName);
                }
            } else if (extensionManager != null) {
                String extensionName = jslibName.substring(0, idx);
                BdfExtensionReference reference = extensionManager.getBdfExtensionReference(extensionName);
                if (reference != null) {
                    JsLibProvider jsLibProvider = (JsLibProvider) reference.getImplementation(JsLibProvider.class);
                    if (jsLibProvider != null) {
                        JsLib jsLib = jsLibProvider.getJsLib(jslibName.substring(idx + 1));
                        if (jsLib != null) {
                            htmlProducer.addJsLib(jsLib);
                        } else {
                            htmlProducer.addLog("[core_jslibs] Unknown extension jslib: " + jslibName);
                        }
                    } else {
                        htmlProducer.addLog("[core_jslibs] extension has no jslib provider: " + extensionName);
                    }
                } else {
                    htmlProducer.addLog("[core_jslibs] Unknown extension: " + extensionName);
                }
            } else {
                htmlProducer.addLog("[core_jslibs] No extension manager: " + jslibName);
            }
        }
        htmlProducer.addJsLib(AppJsLibFactory.newInstance(resourceStorages, appConf));
        htmlProducer.addThemeCss(appConf.getArray(AppConf.CORE_THEMECSSFILES));
        populateAppThemeCss();
        populateSupplementaryCss();
        String bodyCssClass = appConf.getString(AppConf.CORE_BODYCSSCLASS);
        if (bodyCssClass != null) {
            htmlProducer.setBodyCssClass(bodyCssClass);
        }
        populateCustomCss();
    }

    private void populateAppThemeCss() {
        RelativePath themeCssFolderPath = StorageUtils.buildAppResourcePath(appName, "theme/css");
        for (ResourceStorage resourceStorage : resourceStorages) {
            ResourceFolder cssFolder = resourceStorage.getResourceFolder(themeCssFolderPath);
            if (cssFolder != null) {
                for (String resourceName : cssFolder.getResourceNameList()) {
                    if (resourceName.endsWith(".css")) {
                        htmlProducer.addAppThemeCss(appName, resourceName);
                    }
                }
            }
        }
    }

    private void populateSupplementaryCss() {
        RelativePath cssFolderPath = StorageUtils.buildAppResourcePath(appName, "css");
        for (ResourceStorage resourceStorage : resourceStorages) {
            ResourceFolder cssFolder = resourceStorage.getResourceFolder(cssFolderPath);
            if (cssFolder != null) {
                for (String resourceName : cssFolder.getResourceNameList()) {
                    if (resourceName.endsWith(".css")) {
                        htmlProducer.addSupplementaryCss(cssFolderPath.buildChild(resourceName));
                    }
                }
            }
        }
    }

    private void populateCustomCss() {
        RelativePath appCssPath = RelativePath.build("custom/app-" + appName + ".css");
        if (resourceStorages.containsResource(appCssPath)) {
            htmlProducer.addCustomCss(appCssPath);
        }
    }

    private JsLib getThirdLibs() {
        boolean done = false;
        BdfJsLibBuilder builder = BdfJsLibBuilder.init();
        String[] jqueryExtensions = appConf.getArray(AppConf.CORE_JQUERYEXTENSIONS);
        if (jqueryExtensions.length > 0) {
            done = true;
            builder.addThirdLib(JsLibCatalog.JQUERY, jqueryExtensions);
        }
        String[] codemirrorModes = appConf.getArray(AppConf.CORE_CODEMIRRORMODES);
        if (codemirrorModes.length > 0) {
            done = true;
            builder.addThirdLib(JsLibCatalog.CODEMIRROR, codemirrorModes);
        }
        String[] leafletExtensions = appConf.getArray(AppConf.CORE_LEAFLETEXTENSIONS);
        if (leafletExtensions.length > 0) {
            done = true;
            builder.addThirdLib(JsLibCatalog.LEAFLET, leafletExtensions);
        }
        String[] thirdLibs = appConf.getArray(AppConf.CORE_THIRDLIBS);
        if (thirdLibs.length > 0) {
            done = true;
            for (String thirdLib : thirdLibs) {
                builder.addThirdLib(thirdLib);
            }
        }
        if (done) {
            return builder.toJsLib();
        } else {
            return null;
        }
    }

    public static void init(BdfHtmlProducer htmlProducer, AppConf appConf, ResourceStorages resourceStorages, @Nullable ExtensionManager extensionManager) {
        AppInit appInit = new AppInit(htmlProducer, appConf, resourceStorages, extensionManager);
        appInit.run();
    }

}
