// Path: src/main/java/com/github/vedenin/codingchallenge/exceptions/RestClientException.java
// public class RestClientException extends RuntimeException {
//     public RestClientException() {
//     }
// 
//     public RestClientException(String message) {
//         super(message);
//     }
// 
//     public RestClientException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public RestClientException(Throwable cause) {
//         super(cause);
//     }
// 
//     public RestClientException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
//         super(message, cause, enableSuppression, writableStackTrace);
//     }
// }
// 
// Path: src/main/java/com/github/vedenin/codingchallenge/restclient/RestClient.java
// public interface RestClient {
//     BigDecimal getCurrentExchangeRates(CurrencyEnum currecnyFrom, CurrencyEnum currecnyTo);
//     BigDecimal getHistoricalExchangeRates(CurrencyEnum currencyFrom, CurrencyEnum currencyTo, Calendar calendar);
// }
// 
// Path: src/main/java/com/github/vedenin/codingchallenge/common/CurrencyEnum.java
// public enum CurrencyEnum {
//     EUR("EUR", "Euro (EUR)"),
//     USD("USD", "US Dollar (USD)"),
//     GBP("GBP", "British Pound (GBP)"),
//     NZD("NZD", "New Zealand Dollar (NZD)"),
//     AUD("AUD", "Australian Dollar (AUD)"),
//     JPY("JPY", "Japanese Yen (JPY)"),
//     HUF("HUF", "Hungarian Forint (HUF)"),
//     RUB("RUB", "Russian Ruble (RUB)"),
//     PLN("PLN", "Polish Zloty (PLN)");
//     private final String code;
//     private final String description;
// 
//     CurrencyEnum(String code, String description) {
//         this.code = code;
//         this.description = description;
//     }
// 
//     public String getCode() {
//         return code;
//     }
// 
//     public String getDescription() {
//         return description;
//     }
// }


import com.github.vedenin.codingchallenge.exceptions.RestClientException;
import com.github.vedenin.codingchallenge.restclient.RestClient;
import com.github.vedenin.codingchallenge.common.CurrencyEnum;
import org.springframework.stereotype.Service;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Response;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.GregorianCalendar;
import static java.math.BigDecimal.ROUND_FLOOR;
        return getExchangeRates(currencyFrom, currencyTo, getCurrentRates());
    }

    public BigDecimal getHistoricalExchangeRates(CurrencyEnum currencyFrom, CurrencyEnum currencyTo, Calendar calendar) {
        return getExchangeRates(currencyFrom, currencyTo, getHistoricalRates(calendar));
    }

    private BigDecimal getExchangeRates(CurrencyEnum currencyFrom, CurrencyEnum currencyTo, OpenExchangeRatesContainer rates) {
        BigDecimal currencyFromRate = getRates(currencyFrom, rates);
        BigDecimal currencyToRate = getRates(currencyTo, rates);
        return currencyToRate.divide(currencyFromRate, 20, ROUND_FLOOR);
    }

    public OpenExchangeRatesContainer getCurrentRates() {
        return getEntity(URL_LAST, API_ID, OpenExchangeRatesContainer.class);
    }

    public OpenExchangeRatesContainer getHistoricalRates(Calendar date) {
        return getEntity(URL_HISTORY + date.get(Calendar.YEAR) + "-" +
                        getStringWithLeftPadZero(date.get(Calendar.MONTH) + 1) + "-" +
                        getStringWithLeftPadZero(date.get(Calendar.DAY_OF_MONTH)) + ".json?"
                , API_ID, OpenExchangeRatesContainer.class);
    }

    private String getStringWithLeftPadZero(int number) {
        return String.format("%02d", number);
    }

    private static BigDecimal getRates(CurrencyEnum currency, OpenExchangeRatesContainer rates) {
        if (rates.getRates() == null || rates.getRates().get(currency.getCode()) == null) {
// Path: src/main/java/com/github/vedenin/codingchallenge/exceptions/RestClientException.java
// public class RestClientException extends RuntimeException {
//     public RestClientException() {
//     }
// 
//     public RestClientException(String message) {
//         super(message);
//     }
// 
//     public RestClientException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public RestClientException(Throwable cause) {
//         super(cause);
//     }
// 
//     public RestClientException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
//         super(message, cause, enableSuppression, writableStackTrace);
//     }
// }
// 
// Path: src/main/java/com/github/vedenin/codingchallenge/restclient/RestClient.java
// public interface RestClient {
//     BigDecimal getCurrentExchangeRates(CurrencyEnum currecnyFrom, CurrencyEnum currecnyTo);
//     BigDecimal getHistoricalExchangeRates(CurrencyEnum currencyFrom, CurrencyEnum currencyTo, Calendar calendar);
// }
// 
// Path: src/main/java/com/github/vedenin/codingchallenge/common/CurrencyEnum.java
// public enum CurrencyEnum {
//     EUR("EUR", "Euro (EUR)"),
//     USD("USD", "US Dollar (USD)"),
//     GBP("GBP", "British Pound (GBP)"),
//     NZD("NZD", "New Zealand Dollar (NZD)"),
//     AUD("AUD", "Australian Dollar (AUD)"),
//     JPY("JPY", "Japanese Yen (JPY)"),
//     HUF("HUF", "Hungarian Forint (HUF)"),
//     RUB("RUB", "Russian Ruble (RUB)"),
//     PLN("PLN", "Polish Zloty (PLN)");
//     private final String code;
//     private final String description;
// 
//     CurrencyEnum(String code, String description) {
//         this.code = code;
//         this.description = description;
//     }
// 
//     public String getCode() {
//         return code;
//     }
// 
//     public String getDescription() {
//         return description;
//     }
// }


// Path: src/main/java/com/github/vedenin/codingchallenge/restclient/impl/openexchange/OpenExchangeRestClient.java
import com.github.vedenin.codingchallenge.exceptions.RestClientException;
import com.github.vedenin.codingchallenge.restclient.RestClient;
import com.github.vedenin.codingchallenge.common.CurrencyEnum;
import org.springframework.stereotype.Service;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Response;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.GregorianCalendar;
import static java.math.BigDecimal.ROUND_FLOOR;

        return getExchangeRates(currencyFrom, currencyTo, getCurrentRates());
    }

    public BigDecimal getHistoricalExchangeRates(CurrencyEnum currencyFrom, CurrencyEnum currencyTo, Calendar calendar) {
        return getExchangeRates(currencyFrom, currencyTo, getHistoricalRates(calendar));
    }

    private BigDecimal getExchangeRates(CurrencyEnum currencyFrom, CurrencyEnum currencyTo, OpenExchangeRatesContainer rates) {
        BigDecimal currencyFromRate = getRates(currencyFrom, rates);
        BigDecimal currencyToRate = getRates(currencyTo, rates);
        return currencyToRate.divide(currencyFromRate, 20, ROUND_FLOOR);
    }

    public OpenExchangeRatesContainer getCurrentRates() {
        return getEntity(URL_LAST, API_ID, OpenExchangeRatesContainer.class);
    }

    public OpenExchangeRatesContainer getHistoricalRates(Calendar date) {
        return getEntity(URL_HISTORY + date.get(Calendar.YEAR) + "-" +
                        getStringWithLeftPadZero(date.get(Calendar.MONTH) + 1) + "-" +
                        getStringWithLeftPadZero(date.get(Calendar.DAY_OF_MONTH)) + ".json?"
                , API_ID, OpenExchangeRatesContainer.class);
    }

    private String getStringWithLeftPadZero(int number) {
        return String.format("%02d", number);
    }

    private static BigDecimal getRates(CurrencyEnum currency, OpenExchangeRatesContainer rates) {
        if (rates.getRates() == null || rates.getRates().get(currency.getCode()) == null) {
            throw new RestClientException(ERROR_WHILE_GATHERING_INFORMATION +