package pl.banking.storage;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;

import pl.banking.exceptions.ExchangeException;

@XmlRootElement(name = "channel")
public class CurrencyExchangeTable {
    private String baseCurrencyCode;
    private List<CurrencyExchangeRate> currencies;
    
    public CurrencyExchangeTable() {
        super();
    }

    public CurrencyExchangeTable(String baseCurrencyCode, 
                                 List<CurrencyExchangeRate> currencies) {
        super();
        this.baseCurrencyCode = baseCurrencyCode;
        this.currencies = currencies;
    }

    @XmlElement(name = "baseCurrency")
    public String getBaseCurrencyCode() {
        return baseCurrencyCode;
    }

    @XmlElement(name = "item")
    public List<CurrencyExchangeRate> getCurrencies() {
        return currencies;
    }

    public void setBaseCurrencyCode(String baseCurrencyCode) {
        this.baseCurrencyCode = baseCurrencyCode;
    }

    public void setCurrencies(List<CurrencyExchangeRate> currencies) {
        this.currencies = currencies;
    }

    @Override
    public String toString() {
        return "CurrencyExchangeTable [baseCurrencyCode=" + baseCurrencyCode + ", currencies=" + currencies + "]";
    }
    
    public CurrencyExchangeRate find(String currencyCode){
        CurrencyExchangeRate currency = null;
        for(CurrencyExchangeRate c : currencies){
            if(c.getTargetCurrencyCode().equals(currencyCode)){
                currency = c;
                break;
            }
        }
        return currency;
    }
    
    public BigDecimal exchange(String baseCurrency, 
                               String targetCurrency,
                               BigDecimal units) throws ExchangeException{
        CurrencyExchangeRate base = find(baseCurrency);
        if(base == null && !baseCurrency.equals(this.baseCurrencyCode)){
            throw new ExchangeException("Currency code: " + baseCurrency + " not found.");
        }
        CurrencyExchangeRate target = find(targetCurrency);
        if(target == null && !targetCurrency.equals(this.baseCurrencyCode)){
            throw new ExchangeException("Currency code: " + targetCurrency + " not found.");
        }
        
        BigDecimal exchange = new BigDecimal(units.toString());
        if(!baseCurrency.equals(this.baseCurrencyCode)){
            BigDecimal baseEx = base.getExchangeRateAsDecimal();
            exchange = exchange.divide(baseEx, 2, RoundingMode.HALF_UP);
            if(!targetCurrency.equals(this.baseCurrencyCode)){
                BigDecimal targetEx = target.getExchangeRateAsDecimal();
                exchange = exchange.multiply(targetEx).setScale(2, RoundingMode.CEILING);
            }
        }else{
            if(!targetCurrency.equals(this.baseCurrencyCode)){
                BigDecimal targetEx = target.getExchangeRateAsDecimal();
                exchange = exchange.multiply(targetEx).setScale(2, RoundingMode.CEILING);
            }
        }
        
        return exchange;
    }
}
