/*
* Author: Balch
* Created: 9/4/14 12:26 AM
*
* This file is part of MockTrade.
*
* MockTrade is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MockTrade is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MockTrade. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) 2014
*/
package com.balch.mocktrade.services;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.text.format.DateUtils;
import android.util.Log;
import android.util.LongSparseArray;
import com.balch.mocktrade.TradeModelProvider;
import com.balch.mocktrade.TradeApplication;
import com.balch.mocktrade.account.Account;
import com.balch.mocktrade.account.strategies.BaseStrategy;
import com.balch.mocktrade.finance.FinanceModel;
import com.balch.mocktrade.finance.GoogleFinanceModel;
import com.balch.mocktrade.finance.Quote;
import com.balch.mocktrade.investment.Investment;
import com.balch.mocktrade.portfolio.PortfolioModel;
import com.balch.mocktrade.portfolio.PortfolioSqliteModel;
import com.balch.mocktrade.portfolio.PortfolioUpdateBroadcaster;
import com.balch.mocktrade.receivers.QuoteReceiver;
import com.balch.mocktrade.settings.Settings;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class QuoteService extends IntentService {
private static final String TAG = QuoteService.class.getSimpleName();
public static final int SNAPSHOT_DAYS_TO_KEEP = 3650;
public QuoteService() {
super(QuoteService.class.getName());
}
@Override
protected void onHandleIntent(final Intent intent) {
try {
Log.i(TAG, "QuoteService onHandleIntent");
// get the investment list from the db
TradeModelProvider modelProvider = ((TradeModelProvider) this.getApplication());
FinanceModel financeModel = new GoogleFinanceModel(modelProvider.getContext(),
modelProvider.getNetworkRequestProvider(), modelProvider.getSettings());
final PortfolioModel portfolioModel = new PortfolioSqliteModel(modelProvider.getContext(),
modelProvider.getSqlConnection(), modelProvider.getNetworkRequestProvider(),
modelProvider.getSettings());
final List<Investment> investments = portfolioModel.getAllInvestments();
Settings settings = ((TradeModelProvider) this.getApplication()).getSettings();
if (investments.size() > 0) {
final List<Account> accounts = portfolioModel.getAccounts(true);
final LongSparseArray<List<Investment>> accountIdToInvestmentMap = new LongSparseArray<>(accounts.size());
List<String> symbols = new ArrayList<>(investments.size());
for (Investment i : investments) {
symbols.add(i.getSymbol());
// aggregate investments by account
List<Investment> list = accountIdToInvestmentMap.get(i.getAccount().getId());
if (list == null) {
list = new ArrayList<>();
accountIdToInvestmentMap.put(i.getAccount().getId(), list);
}
list.add(i);
}
// get quotes over the wire
Map<String, Quote> quoteMap = financeModel.getQuotes(symbols);
if (quoteMap != null) {
boolean newHasQuotes = false;
for (Investment i : investments) {
try {
Quote quote = quoteMap.get(i.getSymbol());
if (quote != null) {
if (quote.getLastTradeTime().after(i.getLastTradeTime())) {
newHasQuotes = true;
i.setPrevDayClose(quote.getPreviousClose());
i.setPrice(quote.getPrice(), quote.getLastTradeTime());
portfolioModel.updateInvestment(i);
}
}
} catch (Exception ex) {
Log.e(TAG, "updateInvestment exception", ex);
}
}
boolean isFirstSyncOfDay = !DateUtils.isToday(settings.getLastSyncTime());
if (isFirstSyncOfDay) {
portfolioModel.purgeSnapshots(SNAPSHOT_DAYS_TO_KEEP);
}
if (newHasQuotes) {
portfolioModel.createSnapshotTotals(accounts, accountIdToInvestmentMap);
}
processAccountStrategies(accounts, accountIdToInvestmentMap, quoteMap, isFirstSyncOfDay);
settings.setLastSyncTime(System.currentTimeMillis());
startService(WearSyncService.getIntent(getApplicationContext()));
}
}
// if the market is closed reset alarm to next market open time
if (!financeModel.isInPollTime()) {
TradeApplication.backupDatabase(getApplicationContext(), true);
financeModel.setQuoteServiceAlarm();
}
} catch (Exception ex) {
Log.e(TAG, "onHandleIntent exception", ex);
} finally {
PortfolioUpdateBroadcaster.broadcast(QuoteService.this);
QuoteReceiver.completeWakefulIntent(intent);
}
}
public static Intent getIntent(Context context) {
return new Intent(context, QuoteService.class);
}
protected void processAccountStrategies(List<Account> accounts,
LongSparseArray<List<Investment>> accountIdToInvestmentMap,
Map<String, Quote> quoteMap, boolean doDailyUpdate) {
for (Account account : accounts) {
Class<? extends BaseStrategy> strategyClazz = account.getStrategy().getStrategyClazz();
if (strategyClazz != null) {
try {
TradeModelProvider modelProvider = ((TradeModelProvider)this.getApplication());
BaseStrategy strategy = BaseStrategy.createStrategy(strategyClazz,
modelProvider.getContext(), modelProvider.getNetworkRequestProvider(),
modelProvider.getSqlConnection(), modelProvider.getSettings());
if (doDailyUpdate) {
strategy.dailyUpdate(account, accountIdToInvestmentMap.get(account.getId()), quoteMap);
}
strategy.pollUpdate(account, accountIdToInvestmentMap.get(account.getId()), quoteMap);
} catch (Exception ex) {
Log.e(TAG, "Error calling strategy.pollUpdate", ex);
}
}
}
}
}