/* BdfServer - Copyright (c) 2015-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.tools.exportation.transformation;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.configuration.PathConfiguration;
import fr.exemole.bdfserver.tools.BdfURI;
import fr.exemole.bdfserver.tools.docstream.DocStreamFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import net.mapeadores.opendocument.io.OdSource;
import net.mapeadores.opendocument.io.OdUtils;
import net.mapeadores.opendocument.io.Pictures;
import net.mapeadores.opendocument.transform.PictureHandler;
import net.mapeadores.util.io.DocStream;
import net.mapeadores.util.io.IOUtils;


/**
 *
 * @author Vincent Calame
 */
public class BdfPictureHandler extends PictureHandler {

    private final BdfServer bdfServer;
    private final PathConfiguration pathConfiguration;
    private final Map<URI, String> pictureHrefMap = new LinkedHashMap<URI, String>();
    private int current = 1;

    public BdfPictureHandler(BdfServer bdfServer, PathConfiguration pathConfiguration) {
        this.bdfServer = bdfServer;
        this.pathConfiguration = pathConfiguration;
    }

    @Override
    public String checkHref(String href) {
        URI uri = BdfURI.toURI(href, null);
        if (uri == null) {
            return null;
        }
        String scheme = uri.getScheme();
        if (!scheme.equals("bdf")) {
            return null;
        }
        String checkedHref = pictureHrefMap.get(uri);
        if (checkedHref == null) {
            int idx = href.lastIndexOf(".");
            int idx2 = href.lastIndexOf("/");
            if (idx2 > idx) {
                idx = -1;
            }
            if (idx != -1) {
                checkedHref = "Pictures/bdf-" + current + "." + href.substring(idx + 1);
            } else {
                checkedHref = "Pictures/bdf-" + current;
            }
            current++;
            pictureHrefMap.put(uri, checkedHref);
        }
        return checkedHref;
    }

    @Override
    public Pictures toPictures() {
        int size = pictureHrefMap.size();
        Pictures.Entry[] pictureArray = new Pictures.Entry[size];
        int p = 0;
        for (Map.Entry<URI, String> entry : pictureHrefMap.entrySet()) {
            pictureArray[p] = new InternalPictureEntry(bdfServer, pathConfiguration, entry.getValue(), entry.getKey());
            p++;
        }
        List<Pictures.Entry> pictureList = OdUtils.wrap(pictureArray);
        return new BdfPictures(pictureList);
    }


    private static class BdfPictures implements Pictures {

        private final List<Pictures.Entry> pictureList;

        private BdfPictures(List<Pictures.Entry> pictureList) {
            this.pictureList = pictureList;
        }

        @Override
        public List<Entry> getEntryList() {
            return pictureList;
        }

    }


    private static class InternalPictureEntry implements Pictures.Entry {

        private final BdfServer bdfServer;
        private PathConfiguration pathConfiguration;
        private final String href;
        private final URI uri;

        private InternalPictureEntry(BdfServer bdfServer, PathConfiguration pathConfiguration, String href, URI uri) {
            this.bdfServer = bdfServer;
            this.pathConfiguration = pathConfiguration;
            this.href = href;
            this.uri = uri;
        }

        @Override
        public String getHref() {
            return href;
        }

        @Override
        public OdSource getOdSource() {
            DocStream docStream = DocStreamFactory.buildDocStream(bdfServer, pathConfiguration, uri);
            if (docStream != null) {
                return new DocStreamOdSource(docStream);
            }
            return OdUtils.EMPTY_ODSOURCE;
        }

    }


    private static class DocStreamOdSource implements OdSource {

        private final DocStream docStream;

        private DocStreamOdSource(DocStream docStream) {
            this.docStream = docStream;
        }

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

    }

}
