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

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.managers.UiManager;
import fr.exemole.bdfserver.api.ui.IncludeUi;
import fr.exemole.bdfserver.api.ui.UiComponent;
import fr.exemole.bdfserver.api.ui.UiComponents;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import net.fichotheque.Fichotheque;
import net.fichotheque.Metadata;
import net.fichotheque.Subset;
import net.fichotheque.addenda.Addenda;
import net.fichotheque.album.Album;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.sphere.Sphere;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.utils.CorpusMetadataUtils;
import net.mapeadores.opendocument.io.OdSource;
import net.mapeadores.opendocument.io.OdXML;
import net.mapeadores.opendocument.io.OdZip;
import net.mapeadores.opendocument.io.OdZipEngine;
import net.mapeadores.util.io.StreamProducer;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.LangsUtils;
import net.mapeadores.util.mimetype.MimeTypeConstants;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.Labels;
import net.mapeadores.util.text.Phrase;
import net.mapeadores.util.xml.AppendableXMLWriter;
import net.mapeadores.util.xml.XMLPart;
import net.mapeadores.util.xml.XMLUtils;
import net.mapeadores.util.xml.XMLWriter;


/**
 *
 * @author Vincent Calame
 */
public class LabelsOdsProducer implements StreamProducer {

    private final String fileName;
    private final BdfServer bdfServer;

    public LabelsOdsProducer(BdfServer bdfServer, String fileName) {
        this.fileName = fileName;
        this.bdfServer = bdfServer;
    }

    @Override
    public String getMimeType() {
        return MimeTypeConstants.ODS;
    }

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

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

    @Override
    public void writeStream(OutputStream outputStream) throws IOException {
        OdZipEngine.run(outputStream, OdZip.spreadSheet()
                .contentOdSource(new ContentOdSource())
        );
    }


    private class ContentOdSource implements OdSource {

        private ContentOdSource() {
        }

        @Override
        public void writeStream(OutputStream outputStream) throws IOException {
            BufferedWriter buf = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
            AppendableXMLWriter xmlWriter = XMLUtils.toXMLWriter(buf);
            xmlWriter.appendXMLDeclaration();
            LabelsXMLPart labelsXMLPart = new LabelsXMLPart(xmlWriter, bdfServer);
            labelsXMLPart.start();
            labelsXMLPart.addTable();
            labelsXMLPart.end();
            buf.flush();
        }

    }


    private static class LabelsXMLPart extends XMLPart {

        private final UiManager uiManager;
        private final Fichotheque fichotheque;
        private final Lang[] langArray;

        private LabelsXMLPart(XMLWriter xmlWriter, BdfServer bdfServer) {
            super(xmlWriter);
            uiManager = bdfServer.getUiManager();
            fichotheque = bdfServer.getFichotheque();
            langArray = LangsUtils.toArray(bdfServer.getLangConfiguration().getWorkingLangs());
        }

        public void start() throws IOException {
            OdXML.openDocumentContent(this);
            OdXML.openBody(this);
            OdXML.openSpreadsheet(this);
        }

        public void end() throws IOException {
            OdXML.closeSpreadsheet(this);
            OdXML.closeBody(this);
            OdXML.closeDocumentContent(this);
        }

        public void addTable() throws IOException {
            OdXML.openTable(this, "libs");
            addFirstRow();
            addMetadata(fichotheque.getFichothequeMetadata(), "fichotheque");
            for (Corpus corpus : fichotheque.getCorpusList()) {
                addMetadata(corpus);
                addCorpus(corpus);
            }
            for (Thesaurus thesaurus : fichotheque.getThesaurusList()) {
                addMetadata(thesaurus);
            }
            for (Sphere sphere : fichotheque.getSphereList()) {
                addMetadata(sphere);
            }
            for (Album album : fichotheque.getAlbumList()) {
                addMetadata(album);
            }
            for (Addenda addenda : fichotheque.getAddendaList()) {
                addMetadata(addenda);
            }
            OdXML.closeTable(this);
        }

        private void addMetadata(Subset subset) throws IOException {
            addMetadata(subset.getMetadata(), subset.getSubsetKeyString());
        }

        private void addMetadata(Metadata metadata, String rootKey) throws IOException {
            addLabelRow(rootKey + "/title", metadata.getTitleLabels());
            for (Phrase phrase : metadata.getPhrases()) {
                String key = rootKey + "/phrase_" + phrase.getName();
                addLabelRow(key, phrase);
            }

        }

        private void addCorpus(Corpus corpus) throws IOException {
            String rootKey = corpus.getSubsetKeyString();
            for (CorpusField corpusField : CorpusMetadataUtils.getCorpusFieldList(corpus.getCorpusMetadata())) {
                String key = rootKey + "/" + corpusField.getFieldString();
                addLabelRow(key, corpusField.getLabels());
            }
            UiComponents uiComponents = uiManager.getMainUiComponents(corpus);
            for (UiComponent uiComponent : uiComponents.getUiComponentList()) {
                if (uiComponent instanceof IncludeUi) {
                    IncludeUi includeUi = (IncludeUi) uiComponent;
                    Labels customLabels = includeUi.getCustomLabels();
                    if (customLabels != null) {
                        String key = rootKey + "/" + includeUi.getName();
                        addLabelRow(key, customLabels);
                    }
                }
            }
        }

        private void addFirstRow() throws IOException {
            OdXML.openTableRow(this);
            OdXML.addStringTableCell(this, "key");
            for (Lang lang : langArray) {
                OdXML.addStringTableCell(this, "lib_" + lang.toString());
            }
            OdXML.closeTableRow(this);
        }

        private void addLabelRow(String key, Labels labels) throws IOException {
            OdXML.openTableRow(this);
            OdXML.addStringTableCell(this, key);
            for (Lang lang : langArray) {
                Label label = labels.getLabel(lang);
                if (label == null) {
                    OdXML.addEmptyTableCell(this);
                } else {
                    OdXML.addStringTableCell(this, label.getLabelString());
                }
            }
            OdXML.closeTableRow(this);
        }

    }

}
