// Path: app/src/main/java/de/czyrux/store/core/data/util/TimeDelayer.java
// public class TimeDelayer {
// 
//     private static final int MAX_DEFAULT_DELAY = 2000; // 2 sec
//     private final Random random;
// 
//     public TimeDelayer() {
//         random = new Random(System.nanoTime());
//     }
// 
//     public void delay(int maxTime) {
//         try {
//             Thread.sleep(random.nextInt(maxTime));
//         } catch (InterruptedException e) {
//             e.printStackTrace();
//         }
//     }
// 
//     public void delay() {
//         delay(MAX_DEFAULT_DELAY);
//     }
// }
// 
// Path: app/src/main/java/de/czyrux/store/core/domain/cart/Cart.java
// public class Cart {
// 
//     public static final Cart EMPTY = new Cart(Collections.emptyList());
//     public final List<CartProduct> products;
// 
//     public Cart(List<CartProduct> products) {
//         this.products = products;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         Cart cart = (Cart) o;
// 
//         return products != null ? products.equals(cart.products) : cart.products == null;
// 
//     }
// 
//     @Override
//     public int hashCode() {
//         return products != null ? products.hashCode() : 0;
//     }
// }
// 
// Path: app/src/main/java/de/czyrux/store/core/domain/cart/CartBuilder.java
// public class CartBuilder {
// 
//     private static final int DEFAULT_CAPACITY = 10;
//     private static final int NOT_FOUND = -1;
// 
//     private final List<CartProduct> products;
// 
//     private CartBuilder(List<CartProduct> products) {
//         this.products = products;
//     }
// 
//     public static CartBuilder from(Cart cart) {
//         if (cart.products == null) {
//             return empty();
//         }
// 
//         return new CartBuilder(new ArrayList<>(cart.products));
//     }
// 
//     public static CartBuilder empty() {
//         return new CartBuilder(new ArrayList<>(DEFAULT_CAPACITY));
//     }
// 
//     public CartBuilder addProduct(CartProduct product) {
//         int index = getProductIndexBySku(product.sku);
//         if (index != NOT_FOUND) {
//             CartProduct includedProduct = products.get(index);
//             int totalQuantity = product.quantity + includedProduct.quantity;
//             products.set(index, new CartProduct(product.sku, product.title, product.imageUrl, product.price, totalQuantity));
//         } else {
//             products.add(product);
//         }
// 
//         return this;
//     }
// 
//     public CartBuilder removeProduct(CartProduct product) {
//         int index = getProductIndexBySku(product.sku);
//         if (index != NOT_FOUND) {
//             CartProduct includedProduct = products.get(index);
//             int newQuantity = includedProduct.quantity - product.quantity;
//             if (newQuantity <= 0) {
//                 products.remove(index);
//             } else {
//                 products.set(index, new CartProduct(product.sku, product.title, product.imageUrl, product.price, newQuantity));
//             }
//         }
// 
//         return this;
//     }
// 
//     @Nullable
//     private int getProductIndexBySku(String sku) {
//         for (int i = 0; i < products.size(); i++) {
//             if (sku.equalsIgnoreCase(products.get(i).sku)) {
//                 return i;
//             }
//         }
// 
//         return NOT_FOUND;
//     }
// 
//     public Cart build() {
//         return new Cart(products);
//     }
// }
// 
// Path: app/src/main/java/de/czyrux/store/core/domain/cart/CartDataSource.java
// public interface CartDataSource {
// 
//     Single<Cart> getCart();
// 
//     Single<Cart> addProduct(CartProduct cartProduct);
// 
//     Single<Cart> removeProduct(CartProduct cartProduct);
// 
//     Single<Cart> emptyCart();
// }
// 
// Path: app/src/main/java/de/czyrux/store/core/domain/cart/CartProduct.java
// public class CartProduct extends Product {
// 
//     public final int quantity;
// 
//     public CartProduct(String sku, String title, String imageUrl, double price, int quantity) {
//         super(sku, title, imageUrl, price);
//         this.quantity = quantity;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
//         if (!super.equals(o)) return false;
// 
//         CartProduct product = (CartProduct) o;
// 
//         return quantity == product.quantity;
// 
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = super.hashCode();
//         result = 31 * result + quantity;
//         return result;
//     }
// 
//     @Override
//     public String toString() {
//         final StringBuilder sb = new StringBuilder("CartProduct{");
//         sb.append("quantity=").append(quantity);
//         sb.append('}');
//         return sb.toString();
//     }
// }


import de.czyrux.store.core.data.util.TimeDelayer;
import de.czyrux.store.core.domain.cart.Cart;
import de.czyrux.store.core.domain.cart.CartBuilder;
import de.czyrux.store.core.domain.cart.CartDataSource;
import de.czyrux.store.core.domain.cart.CartProduct;
import io.reactivex.Single;
package de.czyrux.store.core.data.sources;


public class InMemoryCartDataSource implements CartDataSource {

    private final TimeDelayer timeDelayer;
    private Cart cart;

    public InMemoryCartDataSource(TimeDelayer timeDelayer) {
        this.timeDelayer = timeDelayer;
        this.cart = Cart.EMPTY;
    }

    @Override
    public synchronized Single<Cart> getCart() {
        return Single.fromCallable(() -> {
            timeDelayer.delay();
            return cart;
        });
    }

    @Override
    public synchronized Single<Cart> addProduct(CartProduct cartProduct) {
        return Single.fromCallable(() -> {
            timeDelayer.delay();

            cart = CartBuilder.from(cart)
                    .addProduct(cartProduct)
                    .build();

            return cart;
        });
    }

    @Override
// Path: app/src/main/java/de/czyrux/store/core/data/util/TimeDelayer.java
// public class TimeDelayer {
// 
//     private static final int MAX_DEFAULT_DELAY = 2000; // 2 sec
//     private final Random random;
// 
//     public TimeDelayer() {
//         random = new Random(System.nanoTime());
//     }
// 
//     public void delay(int maxTime) {
//         try {
//             Thread.sleep(random.nextInt(maxTime));
//         } catch (InterruptedException e) {
//             e.printStackTrace();
//         }
//     }
// 
//     public void delay() {
//         delay(MAX_DEFAULT_DELAY);
//     }
// }
// 
// Path: app/src/main/java/de/czyrux/store/core/domain/cart/Cart.java
// public class Cart {
// 
//     public static final Cart EMPTY = new Cart(Collections.emptyList());
//     public final List<CartProduct> products;
// 
//     public Cart(List<CartProduct> products) {
//         this.products = products;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         Cart cart = (Cart) o;
// 
//         return products != null ? products.equals(cart.products) : cart.products == null;
// 
//     }
// 
//     @Override
//     public int hashCode() {
//         return products != null ? products.hashCode() : 0;
//     }
// }
// 
// Path: app/src/main/java/de/czyrux/store/core/domain/cart/CartBuilder.java
// public class CartBuilder {
// 
//     private static final int DEFAULT_CAPACITY = 10;
//     private static final int NOT_FOUND = -1;
// 
//     private final List<CartProduct> products;
// 
//     private CartBuilder(List<CartProduct> products) {
//         this.products = products;
//     }
// 
//     public static CartBuilder from(Cart cart) {
//         if (cart.products == null) {
//             return empty();
//         }
// 
//         return new CartBuilder(new ArrayList<>(cart.products));
//     }
// 
//     public static CartBuilder empty() {
//         return new CartBuilder(new ArrayList<>(DEFAULT_CAPACITY));
//     }
// 
//     public CartBuilder addProduct(CartProduct product) {
//         int index = getProductIndexBySku(product.sku);
//         if (index != NOT_FOUND) {
//             CartProduct includedProduct = products.get(index);
//             int totalQuantity = product.quantity + includedProduct.quantity;
//             products.set(index, new CartProduct(product.sku, product.title, product.imageUrl, product.price, totalQuantity));
//         } else {
//             products.add(product);
//         }
// 
//         return this;
//     }
// 
//     public CartBuilder removeProduct(CartProduct product) {
//         int index = getProductIndexBySku(product.sku);
//         if (index != NOT_FOUND) {
//             CartProduct includedProduct = products.get(index);
//             int newQuantity = includedProduct.quantity - product.quantity;
//             if (newQuantity <= 0) {
//                 products.remove(index);
//             } else {
//                 products.set(index, new CartProduct(product.sku, product.title, product.imageUrl, product.price, newQuantity));
//             }
//         }
// 
//         return this;
//     }
// 
//     @Nullable
//     private int getProductIndexBySku(String sku) {
//         for (int i = 0; i < products.size(); i++) {
//             if (sku.equalsIgnoreCase(products.get(i).sku)) {
//                 return i;
//             }
//         }
// 
//         return NOT_FOUND;
//     }
// 
//     public Cart build() {
//         return new Cart(products);
//     }
// }
// 
// Path: app/src/main/java/de/czyrux/store/core/domain/cart/CartDataSource.java
// public interface CartDataSource {
// 
//     Single<Cart> getCart();
// 
//     Single<Cart> addProduct(CartProduct cartProduct);
// 
//     Single<Cart> removeProduct(CartProduct cartProduct);
// 
//     Single<Cart> emptyCart();
// }
// 
// Path: app/src/main/java/de/czyrux/store/core/domain/cart/CartProduct.java
// public class CartProduct extends Product {
// 
//     public final int quantity;
// 
//     public CartProduct(String sku, String title, String imageUrl, double price, int quantity) {
//         super(sku, title, imageUrl, price);
//         this.quantity = quantity;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
//         if (!super.equals(o)) return false;
// 
//         CartProduct product = (CartProduct) o;
// 
//         return quantity == product.quantity;
// 
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = super.hashCode();
//         result = 31 * result + quantity;
//         return result;
//     }
// 
//     @Override
//     public String toString() {
//         final StringBuilder sb = new StringBuilder("CartProduct{");
//         sb.append("quantity=").append(quantity);
//         sb.append('}');
//         return sb.toString();
//     }
// }


// Path: app/src/main/java/de/czyrux/store/core/data/sources/InMemoryCartDataSource.java
import de.czyrux.store.core.data.util.TimeDelayer;
import de.czyrux.store.core.domain.cart.Cart;
import de.czyrux.store.core.domain.cart.CartBuilder;
import de.czyrux.store.core.domain.cart.CartDataSource;
import de.czyrux.store.core.domain.cart.CartProduct;
import io.reactivex.Single;

package de.czyrux.store.core.data.sources;


public class InMemoryCartDataSource implements CartDataSource {

    private final TimeDelayer timeDelayer;
    private Cart cart;

    public InMemoryCartDataSource(TimeDelayer timeDelayer) {
        this.timeDelayer = timeDelayer;
        this.cart = Cart.EMPTY;
    }

    @Override
    public synchronized Single<Cart> getCart() {
        return Single.fromCallable(() -> {
            timeDelayer.delay();
            return cart;
        });
    }

    @Override
    public synchronized Single<Cart> addProduct(CartProduct cartProduct) {
        return Single.fromCallable(() -> {
            timeDelayer.delay();

            cart = CartBuilder.from(cart)
                    .addProduct(cartProduct)
                    .build();

            return cart;
        });
    }

    @Override
    public synchronized Single<Cart> removeProduct(CartProduct cartProduct) {