package co.smartreceipts.android.model.converters; import android.content.Context; import android.support.annotation.NonNull; import android.text.TextUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import co.smartreceipts.android.R; import co.smartreceipts.android.model.Distance; import co.smartreceipts.android.model.Receipt; import co.smartreceipts.android.model.factory.PriceBuilderFactory; import co.smartreceipts.android.model.factory.ReceiptBuilderFactory; import co.smartreceipts.android.settings.UserPreferenceManager; import co.smartreceipts.android.settings.catalog.UserPreference; /** * An implementation of the {@link ModelConverter} contract, which * allows us to print {@link co.smartreceipts.android.model.Distance} values in a receipt table. Distances * will be summed up based of a given day. * * @author williambaumann */ public class DistanceToReceiptsConverter implements ModelConverter<Distance, Receipt> { private final Context mContext; private final String mDateSeparator; /** * Convenience constructor for this class. * * @param context - the current application {@link Context} * @param preferences - the user's {@link UserPreferenceManager} */ public DistanceToReceiptsConverter(@NonNull Context context, @NonNull UserPreferenceManager preferences) { this(context, preferences.get(UserPreference.General.DateSeparator)); } /** * Default constructor for this class. * * @param context - the current application {@link Context} * @param dateSeparator - the user's preferred date separator (e.g. "/") */ public DistanceToReceiptsConverter(@NonNull Context context, @NonNull String dateSeparator) { mContext = context.getApplicationContext(); mDateSeparator = dateSeparator; } @Override @NonNull public List<Receipt> convert(@NonNull List<Distance> distances) { final int size = distances.size(); final HashMap<String, List<Distance>> distancesPerDay = new HashMap<>(); // First, let's separate our distances to find what occurs each day for (int i = 0; i < size; i++) { final Distance distance = distances.get(i); final String formattedDate = distance.getFormattedDate(mContext, mDateSeparator); if (distancesPerDay.containsKey(formattedDate)) { distancesPerDay.get(formattedDate).add(distance); } else { final List<Distance> distanceList = new ArrayList<>(); distanceList.add(distance); distancesPerDay.put(formattedDate, distanceList); } } final List<Receipt> receipts = new ArrayList<>(distancesPerDay.keySet().size()); for (Map.Entry<String, List<Distance>> entry : distancesPerDay.entrySet()) { if (!entry.getValue().isEmpty()) { receipts.add(generateReceipt(entry.getValue())); } } return receipts; } @NonNull private Receipt generateReceipt(@NonNull List<Distance> distancesThisDay) { if (distancesThisDay.isEmpty()) { throw new IllegalArgumentException("distancesThisDay must not be empty"); } // Set up default values for everything final Distance distance0 = distancesThisDay.get(0); final ReceiptBuilderFactory factory = new ReceiptBuilderFactory(-1); // Randomize the id final ArrayList<String> names = new ArrayList<>(); for (int i = 0; i < distancesThisDay.size(); i++) { final Distance distance = distancesThisDay.get(i); if (!names.contains(distance.getLocation())) { names.add(distance.getLocation()); } } if (names.isEmpty()) { factory.setName(mContext.getString(R.string.distance)); } else { factory.setName(TextUtils.join("; ", names)); } factory.setTrip(distance0.getTrip()); factory.setDate(distance0.getDate()); factory.setImage(null); factory.setIsReimbursable(true); factory.setTimeZone(distance0.getTimeZone()); factory.setCategory(mContext.getString(R.string.distance)); factory.setCurrency(distance0.getTrip().getTripCurrency()); factory.setPrice(new PriceBuilderFactory().setPriceables(distancesThisDay, distance0.getTrip().getTripCurrency()).build()); return factory.build(); } }