@Override
  public Collection<Coin> getChangeFor(int pence, Product p)
      throws NotEnoughChangeException, NotEnoughMoneyException {

    changeInProgress.clear();
    int difference = pence - p.getProductPrice();

    loadConfig();

    if (enoughMoneyProvided(pence, p)) {
      if (enoughChange(difference)) {
        for (Coin coin : Coin.values()) {
          if (isCoinTypeNeeded(coin, difference - getCurrentChange())) {
            supplyThisCoinType(coin, difference - getCurrentChange(), true);
          }
        }
        if (getCurrentChange() != difference)
          throw new NotEnoughChangeException("The machine has run out of change.");
        updateConfig();
      } else {
        throw new NotEnoughChangeException("The machine has run out of change.");
      }
    } else {
      throw new NotEnoughMoneyException("You have not provided enough money.");
    }

    return changeInProgress;
  }
  /**
   * Returns an integer indicating the maximum number of coins available of a specific type.
   *
   * @param difference Amount between the money provided and the product price.
   * @param coin Current coin in the Map<Coin,Integer>
   * @param changeLimits Indicated whether there is an unlimited supply of change in the machine or
   *     not.
   * @return Integer indicating the maximum amount of coins available for distribution.
   */
  private int getCap(int difference, Coin coin, boolean changeLimits) {

    int capExact = difference / coin.getValueAsInt();

    if (changeLimits) {
      int capMachine = availableChangeMachine.get(coin);
      if (capExact >= capMachine) {
        return capMachine;
      }
    }

    return capExact;
  }
  @Override
  public Collection<Coin> getOptimalChangeFor(int pence, Product p) throws NotEnoughMoneyException {

    changeInProgress.clear();
    int difference = pence - p.getProductPrice();

    if (enoughMoneyProvided(pence, p)) {
      for (Coin coin : Coin.values()) {
        if (isCoinTypeNeeded(coin, difference - getCurrentChange())) {
          supplyThisCoinType(coin, difference - getCurrentChange(), false);
        }
      }
    } else {
      throw new NotEnoughMoneyException(
          "You have not provided enough money.\n"
              + "Remeber that 10 pounds need to be entered as 1000 (one thousand pennies), for example.");
    }

    return changeInProgress;
  }
 /**
  * Checks if the current coin in the Map<Coin,Integer> needs to be added to the changeInProgress.
  *
  * @param coin Current coin in the Map<Coin,Integer>
  * @param difference Amount between the money provided and the product price.
  * @return True if the current coin fits the criteria for the return change.
  */
 private boolean isCoinTypeNeeded(Coin coin, int difference) {
   return difference / coin.getValueAsInt() > 0;
 }