package at.outdated.bitcoin.exchange.api.market;

import at.outdated.bitcoin.exchange.api.currency.Currency;
import at.outdated.bitcoin.exchange.api.currency.CurrencyValue;

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * User: ebirn
 * Date: 16.05.13
 * Time: 23:48
 * To change this template use File | Settings | File Templates.
 */
public class ExchangeRateCalculator {

    double[][] rates;



    public ExchangeRateCalculator() {
        int currencyCount = Currency.values().length;

        // init exchange rate matrix
        rates = new double[currencyCount][currencyCount];

        // set exchange rate for a currency with itself to 1
        for(int i=0; i<currencyCount; i++) {
            // initialize rates with NaN
            Arrays.fill(rates[i], Double.NaN);
            rates[i][i] = 1.0;
        }
    }

    public ExchangeRateCalculator(ExchangeRateCalculator other) {

        this.rates = Arrays.copyOf(other.rates, other.rates.length);

        for(int i=0; i<rates.length; i++) {
            rates[i] = Arrays.copyOf(other.rates[i], other.rates[i].length);
        }
    }

    public double getRate(Currency from, Currency to) {
        return rates[from.ordinal()][to.ordinal()];
    }

    public void setRate(Currency from, Currency to, double rate) {
        int fromIdx = from.ordinal();
        int toIdx = to.ordinal();
        rates[fromIdx][toIdx] = rate;
        rates[toIdx][fromIdx] = 1.0 / rate;
    }

    public CurrencyValue calculate(CurrencyValue value, Currency in) {

        double rate = getRate(value.getCurrency(), in);


        //FIXME: this is an incorrect hack: we must have a exchange path for all currencies
        if(Double.isNaN(rate) || Double.isInfinite(rate)) rate = 0.0;

        return new CurrencyValue(value.getValue()*rate, in);
    }
}

@@ -167,16 +167,106 @@
 Value;%0A%0A
+import java.math.BigDecimal;%0Aimport java.math.MathContext;%0Aimport java.math.RoundingMode;%0A
 import j
@@ -482,24 +482,92 @@
     
-double%5B%5D%5B%5D rates
+BigDecimal%5B%5D%5B%5D rates;%0A%0A    MathContext mc = new MathContext(5, RoundingMode.HALF_UP)
 ;%0A%0A%0A
@@ -717,22 +717,26 @@
 s = new 
-double
+BigDecimal
 %5Bcurrenc
@@ -821,16 +821,70 @@
 lf to 1%0A
+        BigDecimal selfRate = new BigDecimal(1, mc);%0A%0A
         
@@ -999,18 +999,12 @@
 i%5D, 
-Double.NaN
+null
 );%0A 
@@ -1028,19 +1028,24 @@
 i%5D%5Bi%5D = 
-1.0
+selfRate
 ;%0A      
@@ -1341,22 +1341,26 @@
  public 
-double
+BigDecimal
  getRate
@@ -1501,22 +1501,26 @@
 ncy to, 
-double
+BigDecimal
  rate) %7B
@@ -1666,18 +1666,50 @@
 %5D = 
-1.0 / rate
+(new BigDecimal(1.0, mc)).divide(rate, mc)
 ;%0A  
@@ -1797,14 +1797,64 @@
     
-double
+// FIXME: this must be all BigDecimal%0A        BigDecimal
  rat
@@ -1996,16 +1996,32 @@
      if(
+rate == null %7C%7C 
 Double.i
@@ -2029,16 +2029,30 @@
 NaN(rate
+.doubleValue()
 ) %7C%7C Dou
@@ -2074,21 +2074,55 @@
 rate
-)) rate = 0.0
+.doubleValue())) rate = new BigDecimal(0.0, mc)
 ;%0A%0A 
@@ -2174,16 +2174,30 @@
 e()*rate
+.doubleValue()
 , in);%0A 

refactor rate calculator to BigDecimal