/* BdfServer_DirectoryStorage - Copyright (c) 2010-2019 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.storage.directory.jdbm;

import fr.exemole.bdfserver.api.storage.BdfStorageException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import jdbm.helper.Serializer;
import net.fichotheque.corpus.fiche.Fiche;
import net.fichotheque.corpus.fiche.FicheAPI;
import net.fichotheque.corpus.fiche.FicheBlocks;
import net.fichotheque.corpus.fiche.Section;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.srz.FichePrimitives;
import net.mapeadores.util.primitives.io.PrimitivesIOFactory;
import net.mapeadores.util.primitives.io.PrimitivesReader;
import net.mapeadores.util.primitives.io.PrimitivesWriter;


/**
 *
 * @author Vincent Calame
 */
public class CorpsFicheSerializer implements Serializer {

    private final FieldKeyCoder fieldKeyCoder;

    public CorpsFicheSerializer(FieldKeyCoder fieldKeyCoder) {
        this.fieldKeyCoder = fieldKeyCoder;
    }

    @Override
    public byte[] serialize(Object obj) throws IOException {
        Input input = (Input) obj;
        FicheAPI fiche = input.getFicheAPI();
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        PrimitivesWriter primWriter = PrimitivesIOFactory.newWriter(output);
        List<Section> sectionList = fiche.getSectionList();
        int sectionSize = sectionList.size();
        primWriter.writeInt(sectionSize);
        for (int i = 0; i < sectionSize; i++) {
            Section section = sectionList.get(i);
            int fieldKeyCode = fieldKeyCoder.askForCode(section);
            primWriter.writeInt(fieldKeyCode);
            FichePrimitives.writeFicheBlocks(primWriter, section);
        }
        return output.toByteArray();
    }

    @Override
    public Object deserialize(byte[] serialized) {
        PrimitivesReader primReader = PrimitivesIOFactory.newReader(serialized);
        try {
            Fiche fiche = new Fiche();
            int sectionCount = primReader.readInt();
            for (int i = 0; i < sectionCount; i++) {
                int fieldKeyCode = primReader.readInt();
                FicheBlocks ficheBlocks = FichePrimitives.readFicheBlocks(primReader);
                if (ficheBlocks.size() > 0) {
                    FieldKey fieldKey = fieldKeyCoder.getFieldKey(fieldKeyCode);
                    if ((fieldKey != null) && (fieldKey.isSection())) {
                        fiche.setSection(fieldKey, ficheBlocks);
                    }
                }
            }
            return new CorpsFiche(fiche);
        } catch (IOException ioe) {
            throw new BdfStorageException(ioe);
        }
    }


    public static class Input {

        private final FicheAPI ficheAPI;

        public Input(FicheAPI ficheAPI) {
            this.ficheAPI = ficheAPI;
        }

        public FicheAPI getFicheAPI() {
            return ficheAPI;
        }

    }

}
