/* FichothequeLib_Tools - Copyright (c) 2020-2023 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 net.fichotheque.tools.corpus;

import net.fichotheque.FichothequeEditor;
import net.fichotheque.corpus.CorpusEditor;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.corpus.fiche.Fiche;
import net.fichotheque.corpus.fiche.FicheAPI;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.CorpusMetadata;
import net.fichotheque.corpus.metadata.CorpusMetadataEditor;
import net.fichotheque.corpus.metadata.ExistingFieldKeyException;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.corpus.metadata.FieldOptionException;
import net.fichotheque.tools.FichothequeTools;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.exceptions.ShouldNotOccurException;
import net.mapeadores.util.primitives.FuzzyDate;
import net.mapeadores.util.text.Label;


/**
 *
 * @author Vincent Calame
 */
public final class CorpusTools {

    private CorpusTools() {

    }

    public static void copy(CorpusEditor corpusEditor, FicheMeta origin, FicheMeta destination, FicheAPI fiche) {
        corpusEditor.setDate(destination, origin.getCreationDate(), false);
        corpusEditor.setDate(destination, origin.getModificationDate(), true);
        FichothequeEditor fichothequeEditor = corpusEditor.getFichothequeEditor();
        for (Attribute attribute : origin.getAttributes()) {
            fichothequeEditor.putAttribute(destination, attribute);
        }
        corpusEditor.saveFiche(destination, fiche);
    }

    public static void copy(CorpusMetadata origin, CorpusMetadataEditor destination) {
        CorpusCloneEngine engine = new CorpusCloneEngine(origin, destination);
        engine.run();
    }

    public static void saveFiche(CorpusEditor corpusEditor, FicheMeta ficheMeta, Fiche fiche, FieldGenerationEngine engine, boolean modificationDate) {
        if (modificationDate) {
            corpusEditor.setDate(ficheMeta, FuzzyDate.current(), true);
        }
        engine.run(ficheMeta, fiche);
        corpusEditor.saveFiche(ficheMeta, fiche);
    }


    private static class CorpusCloneEngine {

        private final CorpusMetadata corpusMetadata;
        private final CorpusMetadataEditor newCorpusMetadataEditor;

        private CorpusCloneEngine(CorpusMetadata corpusMetadata, CorpusMetadataEditor newCorpusMetadataEditor) {
            this.corpusMetadata = corpusMetadata;
            this.newCorpusMetadataEditor = newCorpusMetadataEditor;
        }

        private void run() {
            FichothequeTools.copy(corpusMetadata, newCorpusMetadataEditor, " (2)");
            copyMandatoryField(FieldKey.TITLE);
            copyMandatoryField(FieldKey.LANG);
            copyMandatoryField(FieldKey.OWNERS);
            copySpecialField(FieldKey.SUBTITLE);
            for (CorpusField corpusField : corpusMetadata.getPropList()) {
                copyField(corpusField);
            }
            for (CorpusField corpusField : corpusMetadata.getInfoList()) {
                copyField(corpusField);
            }
            for (CorpusField corpusField : corpusMetadata.getSectionList()) {
                copyField(corpusField);
            }
            newCorpusMetadataEditor.setFieldGeneration(corpusMetadata.getFieldGeneration());
            CorpusField geolocalisationField = corpusMetadata.getGeolocalisationField();
            if (geolocalisationField != null) {
                newCorpusMetadataEditor.setGeolocalisationField(((CorpusMetadata) newCorpusMetadataEditor.getMetadata()).getCorpusField(geolocalisationField.getFieldKey()));
            }
        }

        private void copyMandatoryField(FieldKey fieldKey) {
            CorpusField corpusField = corpusMetadata.getCorpusField(fieldKey);
            CorpusField newCorpusField = ((CorpusMetadata) newCorpusMetadataEditor.getMetadata()).getCorpusField(fieldKey);
            copyField(corpusField, newCorpusField);
        }

        private void copySpecialField(FieldKey fieldKey) {
            CorpusField corpusField = corpusMetadata.getCorpusField(fieldKey);
            if (corpusField == null) {
                return;
            }
            try {
                CorpusField newCorpusField = newCorpusMetadataEditor.createCorpusField(fieldKey, "");
                copyField(corpusField, newCorpusField);
            } catch (ExistingFieldKeyException efke) {
                throw new ShouldNotOccurException("new corpus");
            }
        }

        private void copyField(CorpusField corpusField) {
            try {
                CorpusField newCorpusField = newCorpusMetadataEditor.createCorpusField(corpusField.getFieldKey(), corpusField.getFicheItemType());
                copyField(corpusField, newCorpusField);
            } catch (ExistingFieldKeyException efke) {
                throw new ShouldNotOccurException("new corpus");
            }
        }

        private void copyField(CorpusField corpusField, CorpusField newCorpusField) {
            for (Label label : corpusField.getLabels()) {
                newCorpusMetadataEditor.putFieldLabel(newCorpusField, label);
            }
            try {
                for (String optionName : corpusField.getOptionNameSet()) {
                    newCorpusMetadataEditor.setFieldOption(newCorpusField, optionName, corpusField.getOption(optionName));
                }
            } catch (FieldOptionException foe) {
                throw new ShouldNotOccurException("clone corpus");
            }
        }

    }


}
