// Path: point-of-sale-app/service-sdk/src/main/java/com/google/abmedge/dto/Payment.java
// public class Payment {
// 
//   private UUID id;
//   private List<PaymentUnit> unitList;
//   private PaymentType type;
//   private Number paidAmount;
// 
//   public Payment() {
//   }
// 
//   public Payment(UUID id, List<PaymentUnit> unitList, PaymentType type, Number paidAmount) {
//     this.id = id;
//     this.unitList = unitList;
//     this.type = type;
//     this.paidAmount = paidAmount;
//   }
// 
//   public UUID getId() {
//     return id;
//   }
// 
//   public void setId(UUID id) {
//     this.id = id;
//   }
// 
//   public List<PaymentUnit> getUnitList() {
//     return unitList;
//   }
// 
//   public void setUnitList(List<PaymentUnit> unitList) {
//     this.unitList = unitList;
//   }
// 
//   public PaymentType getType() {
//     return type;
//   }
// 
//   public void setType(PaymentType type) {
//     this.type = type;
//   }
// 
//   public Number getPaidAmount() {
//     return paidAmount;
//   }
// 
//   public void setPaidAmount(Number paidAmount) {
//     this.paidAmount = paidAmount;
//   }
// }
// 
// Path: point-of-sale-app/service-sdk/src/main/java/com/google/abmedge/dto/PaymentUnit.java
// public class PaymentUnit {
// 
//   private UUID itemId;
//   private String name;
//   private long quantity;
//   private Number totalCost;
// 
//   public PaymentUnit() {}
// 
//   public PaymentUnit(UUID itemId, String name, long quantity, Number totalCost) {
//     this.itemId = itemId;
//     this.name = name;
//     this.quantity = quantity;
//     this.totalCost = totalCost;
//   }
// 
//   public UUID getItemId() {
//     return itemId;
//   }
// 
//   public void setItemId(UUID itemId) {
//     this.itemId = itemId;
//   }
// 
//   public String getName() {
//     return name;
//   }
// 
//   public void setName(String name) {
//     this.name = name;
//   }
// 
//   public long getQuantity() {
//     return quantity;
//   }
// 
//   public void setQuantity(long quantity) {
//     this.quantity = quantity;
//   }
// 
//   public Number getTotalCost() {
//     return totalCost;
//   }
// 
//   public void setTotalCost(Number totalCost) {
//     this.totalCost = totalCost;
//   }
// }
// 
// Path: point-of-sale-app/payments/src/main/java/com/google/abmedge/payments/dto/Bill.java
// public class Bill {
// 
//   private Payment payment;
//   private PaymentStatus status;
//   private Number balance;
//   private String printedBill;
// 
//   public Payment getPayment() {
//     return payment;
//   }
// 
//   public Bill setPayment(Payment payment) {
//     this.payment = payment;
//     return this;
//   }
// 
//   public PaymentStatus getStatus() {
//     return status;
//   }
// 
//   public Bill setStatus(PaymentStatus status) {
//     this.status = status;
//     return this;
//   }
// 
//   public Number getBalance() {
//     return balance;
//   }
// 
//   public Bill setBalance(Number balance) {
//     this.balance = balance;
//     return this;
//   }
// 
//   public String getPrintedBill() {
//     return printedBill;
//   }
// 
//   public Bill setPrintedBill(String printedBill) {
//     this.printedBill = printedBill;
//     return this;
//   }
// }
// 
// Path: point-of-sale-app/payments/src/main/java/com/google/abmedge/payments/dto/PaymentStatus.java
// public enum PaymentStatus {
//   SUCCESS("SUCCESS"),
//   FAILED("FAILED");
// 
//   private String status;
// 
//   PaymentStatus(String status) {
//     this.status = status;
//   }
// 
//   public String getStatus() {
//     return status;
//   }
// }


import com.google.abmedge.dto.Payment;
import com.google.abmedge.dto.PaymentUnit;
import com.google.abmedge.payments.dto.Bill;
import com.google.abmedge.payments.dto.PaymentStatus;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
        .setPrintedBill(generatedBill.getLeft());
  }

  /**
   * This method takes in an ID identifying a payment and a {@link Payment} object and generates a
   * string representation of the bill for the payment. This method returns two things: (1) The
   * string representation of the bill and (2) the balance amount on the bill after the total cost
   * is subtracted from the paid amount. An example of the bill generated from this method is
   * provided inline below.
   *
   * @param paymentId an identifier for the {@link Payment} event to be processed
   * @param payment the {@link Payment} activity to be processed that contains all the details about
   *     the items, amount and {@link com.google.abmedge.dto.PaymentType}
   * @return a string {@link Pair} of items where the {@link Pair#getLeft()} contains the string
   *     representation of the bill and the {@link Pair#getRight()} contains the formatted string
   *     value of balance on the bill
   */
  private Pair<String, String> generateBill(UUID paymentId, Payment payment) {
    float total = 0;
    StringBuilder billBuilder = new StringBuilder();
    billBuilder.append(billHeader(paymentId));
    // append an entry per purchase item to the bill
    int itemIndex = 1;
    for (PaymentUnit pu : payment.getUnitList()) {
      billBuilder.append(billItem(itemIndex, pu));
      total += pu.getTotalCost().floatValue();
      itemIndex++;
    }
    billBuilder.append(BILL_HEADER);
    float tax = new Double(total * TAX_VALUE).floatValue();
// Path: point-of-sale-app/service-sdk/src/main/java/com/google/abmedge/dto/Payment.java
// public class Payment {
// 
//   private UUID id;
//   private List<PaymentUnit> unitList;
//   private PaymentType type;
//   private Number paidAmount;
// 
//   public Payment() {
//   }
// 
//   public Payment(UUID id, List<PaymentUnit> unitList, PaymentType type, Number paidAmount) {
//     this.id = id;
//     this.unitList = unitList;
//     this.type = type;
//     this.paidAmount = paidAmount;
//   }
// 
//   public UUID getId() {
//     return id;
//   }
// 
//   public void setId(UUID id) {
//     this.id = id;
//   }
// 
//   public List<PaymentUnit> getUnitList() {
//     return unitList;
//   }
// 
//   public void setUnitList(List<PaymentUnit> unitList) {
//     this.unitList = unitList;
//   }
// 
//   public PaymentType getType() {
//     return type;
//   }
// 
//   public void setType(PaymentType type) {
//     this.type = type;
//   }
// 
//   public Number getPaidAmount() {
//     return paidAmount;
//   }
// 
//   public void setPaidAmount(Number paidAmount) {
//     this.paidAmount = paidAmount;
//   }
// }
// 
// Path: point-of-sale-app/service-sdk/src/main/java/com/google/abmedge/dto/PaymentUnit.java
// public class PaymentUnit {
// 
//   private UUID itemId;
//   private String name;
//   private long quantity;
//   private Number totalCost;
// 
//   public PaymentUnit() {}
// 
//   public PaymentUnit(UUID itemId, String name, long quantity, Number totalCost) {
//     this.itemId = itemId;
//     this.name = name;
//     this.quantity = quantity;
//     this.totalCost = totalCost;
//   }
// 
//   public UUID getItemId() {
//     return itemId;
//   }
// 
//   public void setItemId(UUID itemId) {
//     this.itemId = itemId;
//   }
// 
//   public String getName() {
//     return name;
//   }
// 
//   public void setName(String name) {
//     this.name = name;
//   }
// 
//   public long getQuantity() {
//     return quantity;
//   }
// 
//   public void setQuantity(long quantity) {
//     this.quantity = quantity;
//   }
// 
//   public Number getTotalCost() {
//     return totalCost;
//   }
// 
//   public void setTotalCost(Number totalCost) {
//     this.totalCost = totalCost;
//   }
// }
// 
// Path: point-of-sale-app/payments/src/main/java/com/google/abmedge/payments/dto/Bill.java
// public class Bill {
// 
//   private Payment payment;
//   private PaymentStatus status;
//   private Number balance;
//   private String printedBill;
// 
//   public Payment getPayment() {
//     return payment;
//   }
// 
//   public Bill setPayment(Payment payment) {
//     this.payment = payment;
//     return this;
//   }
// 
//   public PaymentStatus getStatus() {
//     return status;
//   }
// 
//   public Bill setStatus(PaymentStatus status) {
//     this.status = status;
//     return this;
//   }
// 
//   public Number getBalance() {
//     return balance;
//   }
// 
//   public Bill setBalance(Number balance) {
//     this.balance = balance;
//     return this;
//   }
// 
//   public String getPrintedBill() {
//     return printedBill;
//   }
// 
//   public Bill setPrintedBill(String printedBill) {
//     this.printedBill = printedBill;
//     return this;
//   }
// }
// 
// Path: point-of-sale-app/payments/src/main/java/com/google/abmedge/payments/dto/PaymentStatus.java
// public enum PaymentStatus {
//   SUCCESS("SUCCESS"),
//   FAILED("FAILED");
// 
//   private String status;
// 
//   PaymentStatus(String status) {
//     this.status = status;
//   }
// 
//   public String getStatus() {
//     return status;
//   }
// }


// Path: point-of-sale-app/payments/src/main/java/com/google/abmedge/payments/dao/InMemoryPaymentGateway.java
import com.google.abmedge.dto.Payment;
import com.google.abmedge.dto.PaymentUnit;
import com.google.abmedge.payments.dto.Bill;
import com.google.abmedge.payments.dto.PaymentStatus;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

        .setPrintedBill(generatedBill.getLeft());
  }

  /**
   * This method takes in an ID identifying a payment and a {@link Payment} object and generates a
   * string representation of the bill for the payment. This method returns two things: (1) The
   * string representation of the bill and (2) the balance amount on the bill after the total cost
   * is subtracted from the paid amount. An example of the bill generated from this method is
   * provided inline below.
   *
   * @param paymentId an identifier for the {@link Payment} event to be processed
   * @param payment the {@link Payment} activity to be processed that contains all the details about
   *     the items, amount and {@link com.google.abmedge.dto.PaymentType}
   * @return a string {@link Pair} of items where the {@link Pair#getLeft()} contains the string
   *     representation of the bill and the {@link Pair#getRight()} contains the formatted string
   *     value of balance on the bill
   */
  private Pair<String, String> generateBill(UUID paymentId, Payment payment) {
    float total = 0;
    StringBuilder billBuilder = new StringBuilder();
    billBuilder.append(billHeader(paymentId));
    // append an entry per purchase item to the bill
    int itemIndex = 1;
    for (PaymentUnit pu : payment.getUnitList()) {
      billBuilder.append(billItem(itemIndex, pu));
      total += pu.getTotalCost().floatValue();
      itemIndex++;
    }
    billBuilder.append(BILL_HEADER);
    float tax = new Double(total * TAX_VALUE).floatValue();
    float paid = payment.getPaidAmount().floatValue();