// 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;
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.abmedge.payments.dao;


/**
 * This class is a specific implementation of the {@link PaymentGateway} interface. This class does
 * not interact with any external systems to process the payments. Instead, it uses an in-memory map
 * to keep track of all the payment events. This class acts as the default {@link
 * com.google.abmedge.payments.PaymentsController#activePaymentGateway} when either no/invalid
 * environment variable is set against the key 'PAYMENT_GW' or when it is set to 'IN_MEMORY'.
 */
public class InMemoryPaymentGateway implements PaymentGateway {

  private static final Logger LOGGER = LogManager.getLogger(InMemoryPaymentGateway.class);
  private static final Map<UUID, Payment> paymentMap = new ConcurrentHashMap<>();
  private static final String BILL_HEADER =
      "----------------------------------------------------------------------------\n";
  private static final String SPACE = " ";
  private static final String TOTAL = "  Total:";
  private static final String TAX = "  Tax:";
  private static final String PAID = "  Paid:";
  private static final String BALANCE = "  Balance:";
  private static final double TAX_VALUE = 0.1495;

  @Override
// 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;

// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.abmedge.payments.dao;


/**
 * This class is a specific implementation of the {@link PaymentGateway} interface. This class does
 * not interact with any external systems to process the payments. Instead, it uses an in-memory map
 * to keep track of all the payment events. This class acts as the default {@link
 * com.google.abmedge.payments.PaymentsController#activePaymentGateway} when either no/invalid
 * environment variable is set against the key 'PAYMENT_GW' or when it is set to 'IN_MEMORY'.
 */
public class InMemoryPaymentGateway implements PaymentGateway {

  private static final Logger LOGGER = LogManager.getLogger(InMemoryPaymentGateway.class);
  private static final Map<UUID, Payment> paymentMap = new ConcurrentHashMap<>();
  private static final String BILL_HEADER =
      "----------------------------------------------------------------------------\n";
  private static final String SPACE = " ";
  private static final String TOTAL = "  Total:";
  private static final String TAX = "  Tax:";
  private static final String PAID = "  Paid:";
  private static final String BALANCE = "  Balance:";
  private static final double TAX_VALUE = 0.1495;

  @Override
  public Bill pay(Payment payment) {