/* BdfServer - Copyright (c) 2013-2023 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.exportation.transformation.compilers;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.configuration.PathConfiguration;
import fr.exemole.bdfserver.api.interaction.GetConstants;
import fr.exemole.bdfserver.api.storage.StorageContent;
import fr.exemole.bdfserver.api.storage.TemplateStorage;
import fr.exemole.bdfserver.tools.BdfURI;
import fr.exemole.bdfserver.tools.exportation.transformation.TransformationAvailabilities;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import net.fichotheque.exportation.transformation.TemplateKey;
import net.fichotheque.exportation.transformation.TransformationKey;
import net.mapeadores.opendocument.css.parse.CssParser;
import net.mapeadores.opendocument.css.parse.CssSource;
import net.mapeadores.opendocument.css.parse.LogCssErrorHandler;
import net.mapeadores.opendocument.elements.ElementMaps;
import net.mapeadores.util.exceptions.ShouldNotOccurException;
import net.mapeadores.util.logging.LineMessageHandler;
import net.mapeadores.util.logging.LogUtils;
import net.mapeadores.util.logging.MessageHandler;
import net.mapeadores.util.xml.DOMUtils;
import org.xml.sax.SAXException;


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

    public final static String SEVERE_XML = "severe.xml";

    private TemplateCompilerUtils() {
    }

    public static SimpleTemplateCompiler getSimpleTemplateCompiler(String type, BdfServer bdfServer, PathConfiguration pathConfiguration, TemplateKey templateKey, MessageHandler messageHandler) {
        switch (type) {
            case "xslt":
                return new XsltSimpleTemplateCompiler(bdfServer, pathConfiguration, templateKey, messageHandler);
            default:
                return null;
        }
    }

    public static StreamTemplateCompiler getStreamTemplateCompiler(String type, BdfServer bdfServer, PathConfiguration pathConfiguration, TemplateKey templateKey, MessageHandler messageHandler) {
        String extension = templateKey.getExtension();
        TransformationKey transformationKey = templateKey.getTransformationKey();
        if (extension.equals("odt")) {
            switch (type) {
                case "xslt":
                    if (TransformationAvailabilities.acceptXsltOdt(transformationKey)) {
                        return new XsltOdStreamTemplateCompiler(bdfServer, pathConfiguration, templateKey, messageHandler);
                    } else {
                        return null;
                    }
                case "properties":
                    if (TransformationAvailabilities.acceptPropertiesOdt(transformationKey)) {
                        return new PropertiesOdStreamTemplateCompiler(bdfServer, pathConfiguration, templateKey, messageHandler);
                    } else {
                        return null;
                    }
                default:
                    return null;
            }
        } else {
            return null;
        }
    }

    public static InputStream getContentInputStream(TemplateStorage.Unit storageUnit, String contentPath) throws IOException {
        for (StorageContent storageContent : storageUnit.getStorageContentList()) {
            String path = storageContent.getPath();
            if (path.equals(contentPath)) {
                return storageContent.getInputStream();
            }
        }
        return null;
    }

    public static boolean containsTemplateContent(TemplateStorage.Unit storageUnit, String contentPath) {
        for (StorageContent storageContent : storageUnit.getStorageContentList()) {
            String path = storageContent.getPath();
            if (path.equals(contentPath)) {
                return true;
            }
        }
        return false;
    }

    public static String getBaseURI(TemplateKey templateKey) {
        StringBuilder buf = new StringBuilder();
        buf.append("bdf://this/");
        buf.append(GetConstants.TRANSFORMATIONS_ROOT);
        buf.append("/");
        buf.append(templateKey);
        buf.append("/");
        return buf.toString();
    }

    public static ElementMaps parseCss(BdfServer bdfServer, PathConfiguration pathConfiguration, String cssString, String baseURI, String sourceName, LogCssErrorHandler logCssErrorHandler) {
        CssSource cssSource = new InternalCssSource(bdfServer, pathConfiguration, cssString, baseURI, sourceName);
        ElementMaps elementMaps;
        try {
            elementMaps = CssParser.parse(cssSource, logCssErrorHandler);
        } catch (IOException ioe) {
            throw new ShouldNotOccurException(ioe);
        }
        return elementMaps;
    }

    public static boolean testXml(String xmlString, LineMessageHandler lineMessageHandler) {
        try {
            DOMUtils.parseDocument(xmlString);
            return true;
        } catch (SAXException saxe) {
            LogUtils.handleSAXException(SEVERE_XML, saxe, lineMessageHandler);
            return false;
        }
    }


    private static class InternalCssSource implements CssSource {

        private final BdfServer bdfServer;
        private final PathConfiguration pathConfiguration;
        private final String cssString;
        private final String baseURI;
        private final String name;

        private InternalCssSource(BdfServer bdfServer, PathConfiguration pathConfiguration, String cssString, String baseURI, String name) {
            this.bdfServer = bdfServer;
            this.pathConfiguration = pathConfiguration;
            this.cssString = cssString;
            this.baseURI = baseURI;
            this.name = name;
        }

        @Override
        public Reader getReader() throws IOException {
            return new StringReader(cssString);
        }

        @Override
        public CssSource getImportCssSource(String url) {
            return BdfURI.resolveCssSource(bdfServer, pathConfiguration, url, baseURI);
        }

        @Override
        public String getCssSourceURI() {
            return baseURI + name;
        }

    }


}
