/*
* Copyright (c) 2014. ThanksMister 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.thanksmister.btcblue.data;
import android.content.SharedPreferences;
import com.thanksmister.btcblue.data.api.BitcoinAverage;
import com.thanksmister.btcblue.data.api.Bluelytics;
import com.thanksmister.btcblue.data.api.model.Bluelytic;
import com.thanksmister.btcblue.data.api.model.Exchange;
import com.thanksmister.btcblue.data.api.transforms.ResponseToBluelytics;
import com.thanksmister.btcblue.data.api.transforms.ResponseToExchangeList;
import com.thanksmister.btcblue.data.prefs.StringPreference;
import com.thanksmister.btcblue.utils.Doubles;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import rx.Observable;
import rx.functions.Func1;
import timber.log.Timber;
@Singleton
public class ExchangeService
{
public static final String PREFS_DOLLAR_BLUE_EXPIRE_TIME = "pref_dollar_blue_expire";
public static final String PREFS_EXCHANGE_EXPIRE_TIME = "pref_exchange_expire";
public static final String PREFS_SELECTED_EXCHANGE = "selected_exchange";
public static final int CHECK_EXCHANGE_DATA = 2 * 60 * 1000;// 5 minutes
public static final int CHECK_BLUE_DOLLAR_DATA = 60 * 60 * 1000;// 1 HOUR
public static final String USD = "USD";
private final BitcoinAverage bitcoinAverage;
private final Bluelytics blueLytics;
private final SharedPreferences sharedPreferences;
private List<Bluelytic> bluelyticsList;
@Inject
public ExchangeService(SharedPreferences sharedPreferences, BitcoinAverage bitcoinAverage, Bluelytics blueLytics)
{
this.bitcoinAverage = bitcoinAverage;
this.blueLytics = blueLytics;
this.sharedPreferences = sharedPreferences;
this.bluelyticsList = new ArrayList<>();
}
public void setSelectedExchange(String name)
{
StringPreference preference = new StringPreference(sharedPreferences, PREFS_SELECTED_EXCHANGE, "Bitstamp");
preference.set(name);
}
public String getSelectedExchangeName()
{
StringPreference preference = new StringPreference(sharedPreferences, PREFS_SELECTED_EXCHANGE, "Bitstamp");
Timber.d("Selected Name: " + preference.get());
if(preference.get().equals("")) return "Bitstamp";
return preference.get();
}
private Observable<List<Exchange>> getBluelyticsSubscription(final List<Exchange> exchanges)
{
return blueLytics.latestPrice()
.map(new ResponseToBluelytics())
.flatMap(new Func1<List<Bluelytic>, Observable<List<Exchange>>>()
{
@Override
public Observable<List<Exchange>> call(List<Bluelytic> bluelytics)
{
bluelyticsList = bluelytics;
setDollarBlueExpireTime();
return Observable.just(setBlueDollarValues(bluelytics, exchanges));
}
});
}
private List<Exchange> setBlueDollarValues(List<Bluelytic> bluelytics, List<Exchange> exchanges)
{
double official_value_sell = 0;
double official_value_buy = 0;
double blue_value_sell = 0;
double blue_value_buy = 0;
// we only care about the oficial and the average blue rate
for (Bluelytic bluelytic : bluelytics) {
if (bluelytic.source.equals("oficial")) {
official_value_sell = Doubles.convertToDouble(bluelytic.value_sell);
official_value_buy = Doubles.convertToDouble(bluelytic.value_buy);
} else if (bluelytic.source.equals("blue")) {
blue_value_sell = Doubles.convertToDouble(bluelytic.value_sell);
blue_value_buy = Doubles.convertToDouble(bluelytic.value_buy);
}
}
for (Exchange exchange : exchanges) {
exchange.setBlue_ask(String.valueOf(blue_value_sell));
exchange.setBlue_bid(String.valueOf(blue_value_buy));
exchange.setOfficial_ask(String.valueOf(official_value_sell));
exchange.setOfficial_bid(String.valueOf(official_value_buy));
}
return exchanges;
}
public Observable<List<Exchange>> getExchangesObservable()
{
return bitcoinAverage.exchanges(USD)
.map(new ResponseToExchangeList())
.flatMap(new Func1<List<Exchange>, Observable<List<Exchange>>>()
{
@Override
public Observable<List<Exchange>> call(List<Exchange> exchanges)
{
//setExchangeExpireTime();
if (exchanges == null) {
return Observable.empty();
}
if (needToRefreshDollarBlue()) {
return getBluelyticsSubscription(exchanges);
}
return Observable.just(setBlueDollarValues(bluelyticsList, exchanges));
}
});
}
private class ExchangeNameComparator implements Comparator<Exchange>
{
@Override
public int compare(Exchange o1, Exchange o2) {
return o1.getDisplay_name().toLowerCase().compareTo(o2.getDisplay_name().toLowerCase());
}
}
private void setDollarBlueExpireTime()
{
synchronized (this) {
long expire = System.currentTimeMillis() + CHECK_BLUE_DOLLAR_DATA; // 1 hours
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putLong(PREFS_DOLLAR_BLUE_EXPIRE_TIME, expire);
editor.apply();
}
}
private void setExchangeExpireTime()
{
synchronized (this) {
long expire = System.currentTimeMillis() + CHECK_EXCHANGE_DATA; // 1 hours
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putLong(PREFS_EXCHANGE_EXPIRE_TIME, expire);
editor.apply();
}
}
private boolean needToRefreshDollarBlue()
{
if(bluelyticsList == null || bluelyticsList.isEmpty())
return true;
synchronized (this) {
long expiresAt = sharedPreferences.getLong(PREFS_DOLLAR_BLUE_EXPIRE_TIME, -1);
return System.currentTimeMillis() >= expiresAt;
}
}
private boolean needToRefreshExchanges()
{
synchronized (this) {
long expiresAt = sharedPreferences.getLong(PREFS_EXCHANGE_EXPIRE_TIME, -1);
return System.currentTimeMillis() >= expiresAt;
}
}
}