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

import java.util.AbstractList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.RandomAccess;
import net.fichotheque.SubsetKey;
import net.fichotheque.selection.UserCondition;
import net.fichotheque.sphere.Redacteur;


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

    private final Map<Object, UserCondition.Entry> entryMap = new LinkedHashMap<Object, UserCondition.Entry>();

    public UserConditionBuilder() {

    }

    public UserConditionBuilder addSphere(SubsetKey sphereKey) {
        if (!sphereKey.isSphereSubset()) {
            throw new IllegalArgumentException("sphereKey is not a sphere key");
        }
        String key = "[" + sphereKey.getSubsetName() + "]";
        if (!entryMap.containsKey(key)) {
            entryMap.put(key, new InternalEntry(sphereKey));
        }
        return this;
    }

    public UserConditionBuilder addLogin(SubsetKey sphereKey, String login) {
        if (!sphereKey.isSphereSubset()) {
            throw new IllegalArgumentException("sphereKey is not a sphere key");
        }
        if ((login == null) || (login.isEmpty())) {
            throw new IllegalArgumentException("null or empty login");
        }
        String key = login + "[" + sphereKey.getSubsetName() + "]";
        if (!entryMap.containsKey(key)) {
            entryMap.put(key, new InternalLoginEntry(sphereKey, login));
        }
        return this;
    }

    public UserConditionBuilder addId(Redacteur redacteur) {
        return addId(redacteur.getSubsetKey(), redacteur.getId());
    }

    public UserConditionBuilder addId(SubsetKey sphereKey, int id) {
        if (!sphereKey.isSphereSubset()) {
            throw new IllegalArgumentException("sphereKey is not a sphere key");
        }
        if (id < 1) {
            throw new IllegalArgumentException("id < 1");
        }
        String key = "[" + sphereKey.getSubsetName() + "/" + id;
        if (!entryMap.containsKey(key)) {
            entryMap.put(key, new InternalIdEntry(sphereKey, id));
        }
        return this;
    }

    public boolean isEmpty() {
        return (entryMap.isEmpty());
    }

    public UserCondition toUserCondition() {
        List<UserCondition.Entry> entryList = wrap(entryMap.values().toArray(new UserCondition.Entry[entryMap.size()]));
        return new InternalUserCondition(UserCondition.FILTER_SOME, entryList);
    }

    public static UserConditionBuilder init() {
        return new UserConditionBuilder();
    }

    private static List<UserCondition.Entry> wrap(UserCondition.Entry[] array) {
        return new EntryList(array);
    }


    private static class InternalUserCondition implements UserCondition {

        private final String filter;
        private final List<Entry> entryList;

        private InternalUserCondition(String filter, List<Entry> entryList) {
            this.filter = filter;
            this.entryList = entryList;
        }

        @Override
        public String getFilter() {
            return filter;
        }

        @Override
        public List<Entry> getEntryList() {
            return entryList;
        }

    }


    private static class InternalEntry implements UserCondition.Entry {

        private final SubsetKey sphereKey;

        private InternalEntry(SubsetKey sphereKey) {
            this.sphereKey = sphereKey;
        }

        @Override
        public SubsetKey getSphereKey() {
            return sphereKey;
        }

    }


    private static class InternalLoginEntry extends InternalEntry implements UserCondition.LoginEntry {

        private final String login;

        private InternalLoginEntry(SubsetKey sphereKey, String login) {
            super(sphereKey);
            this.login = login;
        }

        @Override
        public String getLogin() {
            return login;
        }

    }


    private static class InternalIdEntry extends InternalEntry implements UserCondition.IdEntry {

        private final int id;

        private InternalIdEntry(SubsetKey sphereKey, int id) {
            super(sphereKey);
            this.id = id;
        }

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

    }


    private static class EntryList extends AbstractList<UserCondition.Entry> implements RandomAccess {

        private final UserCondition.Entry[] array;

        private EntryList(UserCondition.Entry[] array) {
            this.array = array;
        }

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

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

    }

}
