/* BdfServer_Get - Copyright (c) 2020-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.get.instructions;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.instruction.BdfInstruction;
import fr.exemole.bdfserver.api.instruction.BdfInstructionConstants;
import fr.exemole.bdfserver.api.instruction.BdfParameters;
import fr.exemole.bdfserver.api.users.BdfUser;
import fr.exemole.bdfserver.tools.instruction.DefaultBdfParameters;
import fr.exemole.bdfserver.tools.uml.CorpusPumlWriter;
import fr.exemole.bdfserver.tools.uml.DiagramCache;
import fr.exemole.bdfserver.tools.uml.FichothequePumlWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;
import net.fichotheque.Subset;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.Corpus;
import net.mapeadores.util.exceptions.NestedIOException;
import net.mapeadores.util.io.IOUtils;
import net.mapeadores.util.io.StreamProducer;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.MessageLocalisation;
import net.mapeadores.util.mimetype.MimeTypeUtils;
import net.mapeadores.util.servlets.ResponseHandler;
import net.mapeadores.util.servlets.exceptions.ForbiddenException;
import net.mapeadores.util.servlets.handlers.SimpleResponseHandler;
import net.mapeadores.util.servlets.handlers.StreamResponseHandler;
import net.mapeadores.util.text.FileName;
import net.mapeadores.util.uml.PumlUtils;


/**
 *
 * @author Vincent Calame
 */
public class DiagramsInstruction implements BdfInstruction {

    private final BdfServer bdfServer;
    private final String filePath;

    public DiagramsInstruction(BdfServer bdfServer, String filePath) {
        this.bdfServer = bdfServer;
        this.filePath = filePath;
    }

    @Override
    public short getBdfUserNeed() {
        return BdfInstructionConstants.MANDATORY_BDFUSER;
    }

    @Override
    public ResponseHandler runInstruction(BdfUser bdfUser) {
        BdfParameters bdfParameters = new DefaultBdfParameters(bdfServer, bdfUser);
        FileName fileName;
        try {
            fileName = FileName.parse(filePath);
        } catch (ParseException pe) {
            return null;
        }
        String baseName = fileName.getBasename();
        String extension = fileName.getExtension();
        String pumlString = getPumlString(bdfParameters, baseName);
        if (pumlString == null) {
            return null;
        }
        switch (extension) {
            case "puml":
                return SimpleResponseHandler.init(pumlString);
            case "svg":
            case "png":
                try {
                return convert(baseName, extension, pumlString);
            } catch (IOException ioe) {
                throw new NestedIOException(ioe);
            }
            default:
                return null;
        }
    }

    private String getPumlString(BdfParameters bdfParameters, String baseName) {
        boolean isFichothequeAdmin = bdfParameters.getPermissionSummary().isFichothequeAdmin();
        Lang lang = bdfParameters.getWorkingLang();
        MessageLocalisation messageLocalisation = bdfParameters.getMessageLocalisation();
        if (baseName.equals("fichotheque")) {
            if (!isFichothequeAdmin) {
                throw new ForbiddenException();
            }
            return FichothequePumlWriter.toString(bdfServer, lang, messageLocalisation);
        }
        try {
            SubsetKey subsetKey = SubsetKey.parse(baseName);
            Subset subset = bdfServer.getFichotheque().getSubset(subsetKey);
            if (subset == null) {
                return null;
            }
            if (subset instanceof Corpus) {
                if (!isFichothequeAdmin) {
                    if (!bdfParameters.getPermissionSummary().isSubsetAdmin(subsetKey)) {
                        throw new ForbiddenException();
                    }
                }
                return CorpusPumlWriter.toString(bdfServer, lang, messageLocalisation, (Corpus) subset);
            } else {
                return null;
            }
        } catch (ParseException pe) {

        }
        return null;
    }

    private ResponseHandler convert(String name, String extension, String pumlString) throws IOException {
        String pumlEncoded = PumlUtils.encode(pumlString);
        DiagramCache diagramCache = new DiagramCache(bdfServer);
        String mimeType = MimeTypeUtils.DEFAULT_RESOLVER.getMimeType(extension);
        return StreamResponseHandler.init(new FileStreamProducer(mimeType, diagramCache.getFile(name, pumlEncoded, extension)));
    }


    private static class FileStreamProducer implements StreamProducer {

        private final File file;
        private final String mimeType;

        private FileStreamProducer(String mimeType, File file) {
            this.mimeType = mimeType;
            this.file = file;
        }

        @Override
        public String getMimeType() {
            return mimeType;
        }

        @Override
        public String getCharset() {
            return null;
        }

        @Override
        public String getFileName() {
            return null;
        }

        @Override
        public void writeStream(OutputStream outputStream) throws IOException {
            try (InputStream is = new FileInputStream(file)) {
                IOUtils.copy(is, outputStream);
            }
        }

    }

}
