package net.ranides.assira.credentials;

import net.ranides.assira.collection.maps.GenericKey;
import net.ranides.assira.collection.maps.GenericMap;
import net.ranides.assira.collection.query.CQuery;
import net.ranides.assira.collection.query.CQueryBuilder;
import net.ranides.assira.collection.sets.HashSet;
import net.ranides.assira.index.IQuery;
import net.ranides.assira.index.IQueryMap;
import net.ranides.assira.index.IQueryMapTree;
import net.ranides.assira.io.uri.URIUtils;

import java.net.URI;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;

/**
 * @author msieron
 */
public class BasicUserStore implements UserStore {

    private final IQueryMap<GenericMap<String>> tree;

    public BasicUserStore() {
        tree = new IQueryMapTree();
        index(UserProperty.ACCOUNT);
        index(UserProperty.HOST);
        index(UserProperty.PORT);
    }

    private <T> void index(GenericKey<String, T> key) {
        tree.index(key.key(), key);
    }

    @Override
    public CQuery<GenericMap<String>> match(URI uri) {
        Optional<String> login = URIUtils.getLogin(uri);

        if(login.isPresent()) {
            return tree.find()
                .eq(UserProperty.ACCOUNT, login.get())
                .optional().eq(UserProperty.HOST, uri.getHost())
                .optional().eq(UserProperty.PORT, uri.getPort())
                .filter(u -> urimatch(u, uri));
        } else {
            return tree.find()
                .optional().eq(UserProperty.HOST, uri.getHost())
                .optional().eq(UserProperty.PORT, uri.getPort())
                .filter(u -> urimatch(u, uri));
        }



//        Set<GenericMap<String>> target = new HashSet<>();
//
//        IQuery<GenericMap<String>> query = tree.find()
//            .optional().eq(UserProperty.HOST, uri.getHost())
//            .optional().eq(UserProperty.PORT, uri.getPort());
//
//        Optional<String> login = URIUtils.getLogin(uri);
//
//        if(login.isPresent()) {
//            query.eq(UserProperty.ACCOUNT, login.get()).into(target);
//            query.eq(UserProperty.LOGIN, login.get()).into(target);
//            query.filter(u -> urimatch(u, uri))
//        } else {
//            tree.find()
//                .eq(UserProperty.HOST, null)
//                .eq(UserProperty.PORT, null)
//                .filter(u -> urimatch(u, uri))
//                .into(target);
//        }
//
//        return CQueryBuilder.fromStream(() -> target.stream());
    }

    private boolean urimatch(GenericMap<String> u, URI uri) {
        return u.getOptional(UserProperty.URI).map(p -> p.test(uri)).orElse(true);
    }

    @Override
    public CQuery<GenericMap<String>> find(String user) {
        return tree.find().eq(UserProperty.ACCOUNT, user);
    }

    public BasicUserStore add(GenericMap<String> user) {
        tree.put(user);
        return this;
    }

//    public BasicUserStore add(GenericMap<String> user) {
//        tree.put(user);
//        return this;
//    }
}
