/* BdfServer_Multi - Copyright (c) 2018-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.multi.commands;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.storage.directory.bdfdata.StartValues;
import java.util.function.Predicate;
import net.fichotheque.Subset;
import net.fichotheque.SubsetItem;
import net.fichotheque.SubsetKey;
import net.fichotheque.eligibility.SubsetEligibility;
import net.fichotheque.sphere.Redacteur;
import net.fichotheque.sphere.Sphere;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.utils.EligibilityUtils;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.logging.ErrorMessageException;


/**
 *
 * @author Vincent Calame
 */
public class CreationParameters {

    public final static String NEW_TYPE = "new";
    public final static String NEW_WITH_SPHERES_TYPE = "new_with_spheres";
    public final static String NEW_WITH_CENTRAL_TYPE = "new_with_central";
    public final static String DUPLICATE_TYPE = "duplicate";
    private final static SubsetEligibility DEFAUT_SUBSETELIGIBILITY = new DefaultSubsetEligibility();
    private final String type;
    private final String newFichothequeName;
    private final StartValues startValues;
    private final BdfServer sourceBdfServer;
    private final SubsetEligibility subsetEligibility;


    private CreationParameters(String type, String newFichothequeName, StartValues startValues, BdfServer sourceBdfServer) {
        this.type = type;
        this.newFichothequeName = newFichothequeName;
        this.startValues = startValues;
        this.sourceBdfServer = sourceBdfServer;
        this.subsetEligibility = null;
    }

    private CreationParameters(String newFichothequeName, BdfServer sourceBdfServer, SubsetEligibility subsetEligibility) {
        this.type = DUPLICATE_TYPE;
        this.newFichothequeName = newFichothequeName;
        this.startValues = null;
        this.sourceBdfServer = sourceBdfServer;
        this.subsetEligibility = subsetEligibility;
    }

    public String getNewFichothequeName() {
        return newFichothequeName;
    }

    public String getType() {
        return type;
    }

    public BdfServer getSourceBdfServer() {
        return sourceBdfServer;
    }

    public SubsetEligibility getSubsetEligibility() {
        return subsetEligibility;
    }

    public StartValues startValues() {
        return startValues;
    }

    public static CreationParameters initNew(String fichothequeName, StartValues startValues) {
        return new CreationParameters(NEW_TYPE, fichothequeName, startValues, null);
    }

    public static CreationParameters initNewWithSpheres(String fichothequeName, StartValues startValues, BdfServer sourceBdfServer) {
        return new CreationParameters(NEW_WITH_SPHERES_TYPE, fichothequeName, startValues, sourceBdfServer);
    }

    public static CreationParameters initNewWithCentral(String fichothequeName, StartValues startValues) {
        return new CreationParameters(NEW_WITH_CENTRAL_TYPE, fichothequeName, startValues, null);
    }

    public static CreationParameters initDuplicate(String fichothequeName, BdfServer sourceBdfServer, @Nullable SubsetEligibility subsetEligibility) throws ErrorMessageException {
        if (subsetEligibility == null) {
            subsetEligibility = DEFAUT_SUBSETELIGIBILITY;
        } else {
            if (!containsAdmin(sourceBdfServer, subsetEligibility)) {
                throw new ErrorMessageException("_ error.unsupported.needadmin");
            }
        }
        return new CreationParameters(fichothequeName, sourceBdfServer, subsetEligibility);
    }

    private static boolean containsAdmin(BdfServer sourceBdfServer, SubsetEligibility subsetEligibility) {
        for (Redacteur redacteur : sourceBdfServer.getPermissionManager().getAdminRedacteurList()) {
            Sphere sphere = redacteur.getSphere();
            if (subsetEligibility.accept(sphere)) {
                if (subsetEligibility.getPredicate(sphere).test(redacteur)) {
                    return true;
                }
            }
        }
        return false;
    }


    private static class DefaultSubsetEligibility implements SubsetEligibility {

        private DefaultSubsetEligibility() {

        }

        @Override
        public boolean accept(SubsetKey subsetKey) {
            return true;
        }

        @Override
        public Predicate<SubsetItem> getPredicate(Subset subset) {
            if ((subset instanceof Sphere) || (subset instanceof Thesaurus)) {
                return EligibilityUtils.ALL_SUBSETITEM_PREDICATE;
            } else {
                return EligibilityUtils.NONE_SUBSETITEM_PREDICATE;
            }
        }

    }

}
