// Path: src/main/java/shopJava/util/Constants.java
// public interface Constants {
// 
//     int MAX_ORDERS_PER_USER = 10;
// 
//     String MONGODB_URI = "mongodb://localhost:27017";
//     String SHOP_DB_NAME = "shop";
//     String USERS_COLLECTION_NAME = "users";
//     String ORDERS_COLLECTION_NAME = "orders";
// 
//     String HOMER = "homer";
//     String MARGE = "marge";
//     String BART = "bart";
//     String LISA = "lisa";
//     String MAGGIE = "maggie";
// 
//     String[] SIMPSONS = {HOMER, MARGE, BART, LISA, MAGGIE};
// }
// 
// Path: src/main/java/shopJava/util/Util.java
// public static int average(final int totalAmount, final int orderCount) {
//     return orderCount == 0 ? 0 : Math.round((100.0f * totalAmount / orderCount) / 100);
// }
// 
// Path: src/main/java/shopJava/util/Util.java
// public static User checkUserLoggedIn(final Optional<User> optUser, final Credentials credentials) {
// 
//     if (!optUser.isPresent()) {     // replaces if (user != null)
//         throw new RuntimeException(new IllegalAccessException("User unknown: " + credentials.username));
//     }
//     final User user = optUser.get();
//     return checkUserLoggedIn(user, credentials);
// }


import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import shopJava.model.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.*;
import java.util.stream.Stream;
import static com.mongodb.client.model.Filters.eq;
import static java.lang.Thread.sleep;
import static java.util.stream.Collectors.toList;
import static shopJava.util.Constants.*;
import static shopJava.util.Util.average;
import static shopJava.util.Util.checkUserLoggedIn;
                    .find(eq("_id", name))
                    .first();
            return Optional.ofNullable(doc).map(User::new);
        }

        private List<Order> _findOrdersByUsername(final String username) {
            final List<Document> docs = ordersCollection
                    .find(eq("username", username))
                    .into(new ArrayList<>());
            return docs.stream()
                    .map(doc -> new Order(doc))
                    .collect(toList());
        }

        Future<Optional<User>> findUserByName(final String name) {
            Callable<Optional<User>> callable = () -> _findUserByName(name);
            return executor.submit(callable);
        }

        Future<List<Order>> findOrdersByUsername(final String username) {
            Callable<List<Order>> callable = () -> _findOrdersByUsername(username);
            return executor.submit(callable);
        }
    }   // end DAO


    private String logIn(final Credentials credentials) {
        try {
            final Future<Optional<User>> future = dao.findUserByName(credentials.username);
            final Optional<User> optUser = future.get();
// Path: src/main/java/shopJava/util/Constants.java
// public interface Constants {
// 
//     int MAX_ORDERS_PER_USER = 10;
// 
//     String MONGODB_URI = "mongodb://localhost:27017";
//     String SHOP_DB_NAME = "shop";
//     String USERS_COLLECTION_NAME = "users";
//     String ORDERS_COLLECTION_NAME = "orders";
// 
//     String HOMER = "homer";
//     String MARGE = "marge";
//     String BART = "bart";
//     String LISA = "lisa";
//     String MAGGIE = "maggie";
// 
//     String[] SIMPSONS = {HOMER, MARGE, BART, LISA, MAGGIE};
// }
// 
// Path: src/main/java/shopJava/util/Util.java
// public static int average(final int totalAmount, final int orderCount) {
//     return orderCount == 0 ? 0 : Math.round((100.0f * totalAmount / orderCount) / 100);
// }
// 
// Path: src/main/java/shopJava/util/Util.java
// public static User checkUserLoggedIn(final Optional<User> optUser, final Credentials credentials) {
// 
//     if (!optUser.isPresent()) {     // replaces if (user != null)
//         throw new RuntimeException(new IllegalAccessException("User unknown: " + credentials.username));
//     }
//     final User user = optUser.get();
//     return checkUserLoggedIn(user, credentials);
// }


// Path: src/main/java/shopJava/queries/QueryJ02Future.java
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import shopJava.model.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.*;
import java.util.stream.Stream;
import static com.mongodb.client.model.Filters.eq;
import static java.lang.Thread.sleep;
import static java.util.stream.Collectors.toList;
import static shopJava.util.Constants.*;
import static shopJava.util.Util.average;
import static shopJava.util.Util.checkUserLoggedIn;

                    .find(eq("_id", name))
                    .first();
            return Optional.ofNullable(doc).map(User::new);
        }

        private List<Order> _findOrdersByUsername(final String username) {
            final List<Document> docs = ordersCollection
                    .find(eq("username", username))
                    .into(new ArrayList<>());
            return docs.stream()
                    .map(doc -> new Order(doc))
                    .collect(toList());
        }

        Future<Optional<User>> findUserByName(final String name) {
            Callable<Optional<User>> callable = () -> _findUserByName(name);
            return executor.submit(callable);
        }

        Future<List<Order>> findOrdersByUsername(final String username) {
            Callable<List<Order>> callable = () -> _findOrdersByUsername(username);
            return executor.submit(callable);
        }
    }   // end DAO


    private String logIn(final Credentials credentials) {
        try {
            final Future<Optional<User>> future = dao.findUserByName(credentials.username);
            final Optional<User> optUser = future.get();
            final User user = checkUserLoggedIn(optUser, credentials);