/* BdfServer_Commands - Copyright (c) 2013-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.commands.addenda;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.tools.instruction.AbstractBdfCommand;
import fr.exemole.bdfserver.tools.instruction.BdfErrors;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import net.fichotheque.addenda.Addenda;
import net.fichotheque.tools.parsers.DocumentChangeInfo;
import net.fichotheque.utils.AddendaUtils;
import net.mapeadores.util.io.IOUtils;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.mimetype.MimeTypeResolver;
import net.mapeadores.util.primitives.FileLength;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.text.FileName;


/**
 *
 * @author Vincent Calame
 */
public class DocumentFileDownloadCommand extends AbstractBdfCommand {

    public final static String COMMANDNAME = "DocumentFileDownload";
    public final static String URL_PARAMNAME = "url";
    public final static String METHOD_PARAMNAME = "method";
    public final static String URL_METHOD_PARAMVALUE = "url";
    public final static String MIME_METHOD_PARAMVALUE = "mime";
    public final static String PARAM_METHOD_PARAMVALUE = "param";
    public final static String EXTENSION_PARAMNAME = "extension";
    private Addenda addenda;
    private HttpURLConnection httpURLConnection;
    private String basename;
    private String originalBasename;
    private String extension;

    public DocumentFileDownloadCommand(BdfServer bdfServer, RequestMap requestMap) {
        super(bdfServer, requestMap);
    }

    @Override
    public boolean needSynchronisation() {
        return false;
    }

    @Override
    protected void doCommand() throws ErrorMessageException {
        File tmpFile = DocumentFileUploadCommand.getTmpFile(bdfServer, extension);
        try (InputStream is = httpURLConnection.getInputStream(); OutputStream os = new FileOutputStream(tmpFile)) {
            IOUtils.copy(is, os);
        } catch (IOException ioe) {
            throw BdfErrors.ioException(ioe);
        }
        setDone("_ done.addenda.documentfiledownload");
        DocumentChangeInfo documentChangeInfo = DocumentChangeInfo.parse("bn=" + basename + ",tf=" + tmpFile.getName());
        putResultObject(DOCUMENTCHANGEINFO_OBJ, documentChangeInfo);
        putResultObject(STRING_OBJ, originalBasename);
        putResultObject(FILELENGTH_OBJ, new FileLength(tmpFile.length()));
        putResultObject(ADDENDA_OBJ, addenda);
    }

    @Override
    protected void checkParameters() throws ErrorMessageException {
        this.addenda = requestHandler.getMandatoryAddenda();
        String checkedExtension = null;
        String extensionMethod = getMandatory(METHOD_PARAMNAME);
        if (extensionMethod.equals(PARAM_METHOD_PARAMVALUE)) {
            checkedExtension = getMandatory(EXTENSION_PARAMNAME);
            checkedExtension = checkedExtension.toLowerCase();
            if (!AddendaUtils.testExtension(checkedExtension)) {
                throw BdfErrors.error("_ error.wrong.extension", checkedExtension);
            }
        }
        String urlString = getMandatory(URL_PARAMNAME);
        URL documentURL;
        try {
            documentURL = new URL(urlString);
        } catch (MalformedURLException mue) {
            throw BdfErrors.error("_ error.wrong.url", urlString);
        }
        String protocol = documentURL.getProtocol();
        if ((protocol == null) || (protocol.isEmpty())) {
            throw BdfErrors.error("_ error.wrong.url", urlString);
        }
        switch (protocol) {
            case "http":
            case "https":
                break;
            default:
                throw BdfErrors.error("_ error.unknown.url_protocol", protocol);
        }
        try {
            HttpURLConnection urlConnection = (HttpURLConnection) documentURL.openConnection();
            urlConnection.setInstanceFollowRedirects(true);
            urlConnection.connect();
            int code = urlConnection.getResponseCode();
            if (code != 200) {
                throw BdfErrors.error("_ error.exception.url_httpcode", code);
            }
            String bn = "index";
            String urlExtension = "html";
            String path = documentURL.getPath();
            int idx = path.lastIndexOf("/");
            if (idx != -1) {
                String fileNameString = path.substring(idx + 1);
                if (fileNameString.length() > 0) {
                    try {
                        FileName fileName = FileName.parse(fileNameString);
                        bn = fileName.getBasename();
                        urlExtension = fileName.getExtension();
                    } catch (ParseException pe) {
                        bn = fileNameString;
                    }
                }
            }
            if (checkedExtension == null) {
                if (extensionMethod.equals(MIME_METHOD_PARAMVALUE)) {
                    String mimetype = urlConnection.getContentType();
                    if (mimetype != null) {
                        MimeTypeResolver mimeTypeResolver = bdfServer.getMimeTypeResolver();
                        String preferredExtension = mimeTypeResolver.getPreferredExtension(mimetype);
                        if (preferredExtension == null) {
                            preferredExtension = urlExtension;
                        }
                        checkedExtension = preferredExtension;
                    }
                } else {
                    checkedExtension = urlExtension;
                }
            }
            this.httpURLConnection = urlConnection;
            if (!AddendaUtils.testExtension(checkedExtension.toLowerCase())) {
                throw BdfErrors.error("_ error.wrong.extension", bn);
            }
            this.extension = checkedExtension.toLowerCase();
            this.originalBasename = bn;
            this.basename = AddendaUtils.checkBasename(bn, addenda);
        } catch (IOException ioe) {
            throw BdfErrors.error("_ error.exception.url_io", documentURL);
        }
    }

}
