/* BdfServer - 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 fr.exemole.bdfserver.tools.externalsource;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.externalsource.ExternalSourceType;
import java.util.AbstractList;
import java.util.Collections;
import java.util.List;
import java.util.RandomAccess;
import net.fichotheque.externalsource.ExternalItem;
import net.fichotheque.externalsource.ExternalSource;
import net.fichotheque.externalsource.ExternalSourceDef;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.thesaurus.policies.DynamicEditPolicy;
import net.mapeadores.util.localisation.Litteral;


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

    public final static List<ExternalItem> EXTERNALITEM_EMPTYLIST = Collections.emptyList();

    private ExternalSourceUtils() {

    }

    public static ExternalSourceType getMatchingExternalSourceType(ExternalSourceDef externalSourceDef) {
        ExternalSourceType externalSourceType = CoreExternalSourceCatalog.getExternalSourceType(externalSourceDef.getType());
        if (externalSourceType != null) {
            return externalSourceType;
        }
        return getUnknwonType(externalSourceDef);
    }

    public static ExternalSourceType getUnknwonType(ExternalSourceDef externalSourceDef) {
        String type = externalSourceDef.getType();
        ExternalSourceTypeBuilder externalSourceTypeBuilder = ExternalSourceTypeBuilder.init(type)
                .setL10nObject(new Litteral(type));
        for (String name : externalSourceDef.getParamNameSet()) {
            externalSourceTypeBuilder.addParam(name, new Litteral(name));
        }
        return externalSourceTypeBuilder.toExternalSourceType();
    }

    public static List<ExternalSourceType> getAvalaibleTypeList(BdfServer bdfServer, Thesaurus thesaurus) {
        CoreExternalSourceCatalog catalog = new CoreExternalSourceCatalog(bdfServer);
        return catalog.getAvalaibleTypeList(thesaurus);
    }

    public static List<ExternalSourceType> getDataUiAvalaibleTypeList(BdfServer bdfServer) {
        CoreExternalSourceCatalog catalog = new CoreExternalSourceCatalog(bdfServer);
        return catalog.getDataUiAvalaibleTypeList();
    }

    public static List<ExternalSourceType.Param> wrap(ExternalSourceType.Param[] array) {
        return new ExternalSourceTypeParamList(array);
    }

    public static ExternalSourceType.Param toParam(String name, Object paramL10nObject) {
        if (name == null) {
            throw new IllegalArgumentException("name is null");
        }
        if (paramL10nObject == null) {
            throw new IllegalArgumentException("paramL10nObject is null");
        }
        return new ExternalSourceTypeParam(name, paramL10nObject);
    }

    public static ExternalSource getExternalSource(BdfServer bdfServer, Thesaurus thesaurus) {
        DynamicEditPolicy dynamicEditPolicy = bdfServer.getPolicyManager().getPolicyProvider().getDynamicEditPolicy(thesaurus);
        if (!dynamicEditPolicy.getType().equals(DynamicEditPolicy.EXTERNAL_TYPE)) {
            return null;
        }
        return bdfServer.getExternalSourceProvider().getExternalSource(((DynamicEditPolicy.External) dynamicEditPolicy).getExternalSourceDef());
    }

    public static ExternalItem.Id toExternalItem(int id, String title, String description) {
        if (title == null) {
            title = "";
        }
        if (description == null) {
            description = "";
        }
        return new ExternalItemId(id, title, description);
    }

    public static ExternalItem.Idalpha toExternalItem(String idalpha, String title, String description) {
        if (title == null) {
            title = "";
        }
        if (description == null) {
            description = "";
        }
        return new ExternalItemIdalpha(idalpha, title, description);
    }


    private static class ExternalSourceTypeParam implements ExternalSourceType.Param {

        private final String name;
        private final Object l10nObject;

        private ExternalSourceTypeParam(String name, Object l10nObject) {
            this.name = name;
            this.l10nObject = l10nObject;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public Object getL10nObject() {
            return l10nObject;
        }

    }


    private static class ExternalSourceTypeParamList extends AbstractList<ExternalSourceType.Param> implements RandomAccess {

        private final ExternalSourceType.Param[] array;

        private ExternalSourceTypeParamList(ExternalSourceType.Param[] array) {
            this.array = array;
        }

        @Override
        public int size() {
            return array.length;
        }

        @Override
        public ExternalSourceType.Param get(int index) {
            return array[index];
        }

    }


    private static class ExternalItemId implements ExternalItem.Id {

        private final int id;
        private final String title;
        private final String description;

        private ExternalItemId(int id, String title, String description) {
            this.id = id;
            this.title = title;
            this.description = description;
        }

        @Override
        public int getId() {
            return id;
        }

        @Override
        public String getTitle() {
            return title;
        }

        @Override
        public String getDescription() {
            return description;
        }

    }


    private static class ExternalItemIdalpha implements ExternalItem.Idalpha {

        private final String idalpha;
        private final String title;
        private final String description;

        private ExternalItemIdalpha(String idalpha, String title, String description) {
            this.idalpha = idalpha;
            this.title = title;
            this.description = description;
        }

        @Override
        public String getIdalpha() {
            return idalpha;
        }

        @Override
        public String getTitle() {
            return title;
        }

        @Override
        public String getDescription() {
            return description;
        }

    }

}
