/*
* 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.portfolio;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.LongSparseArray;
import com.balch.android.app.framework.sql.SqlConnection;
import com.balch.mocktrade.NetworkRequestProvider;
import com.balch.mocktrade.account.Account;
import com.balch.mocktrade.account.AccountSqliteModel;
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.investment.InvestmentSqliteModel;
import com.balch.mocktrade.order.Order;
import com.balch.mocktrade.order.OrderExecutionException;
import com.balch.mocktrade.order.OrderResult;
import com.balch.mocktrade.order.OrderSqliteModel;
import com.balch.mocktrade.services.OrderService;
import com.balch.mocktrade.settings.Settings;
import com.balch.mocktrade.shared.PerformanceItem;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class PortfolioSqliteModel implements PortfolioModel {
private final AccountSqliteModel accountModel;
private final InvestmentSqliteModel investmentModel;
private final OrderSqliteModel orderModel;
private final FinanceModel financeModel;
private final SnapshotTotalsSqliteModel snapshotTotalsModel;
private final SqlConnection sqlConnection;
public PortfolioSqliteModel(Context context, SqlConnection sqlConnection,
NetworkRequestProvider networkRequestProvider,
Settings settings) {
this.sqlConnection = sqlConnection;
this.accountModel = new AccountSqliteModel(context, networkRequestProvider, sqlConnection, settings);
this.investmentModel = new InvestmentSqliteModel(sqlConnection);
this.orderModel = new OrderSqliteModel(context, networkRequestProvider, sqlConnection, settings);
this.snapshotTotalsModel = new SnapshotTotalsSqliteModel(sqlConnection, settings);
this.financeModel = new GoogleFinanceModel(context, networkRequestProvider, settings);
}
@Override
public List<Account> getAccounts(boolean allAccounts) {
return accountModel.getAccounts(allAccounts);
}
@Override
public Account getAccount(long accountID) {
return accountModel.getAccount(accountID);
}
@Override
public void createAccount(Account account) {
accountModel.createAccount(account);
}
@Override
public void deleteAccount(Account account) {
accountModel.deleteAccount(account);
}
@Override
public List<Investment> getAllInvestments() {
return investmentModel.getAllInvestments();
}
@Override
public List<Investment> getInvestments(Long accountId) {
return investmentModel.getInvestments(accountId);
}
@Override
public void createOrder(Order order) {
orderModel.createOrder(order);
}
public List<Order> getOpenOrders() {
return orderModel.getOpenOrders();
}
@Override
public boolean updateInvestment(Investment investment) {
return investmentModel.updateInvestment(investment);
}
@Override
public void processOrders(Context context, boolean forceExecution) {
if (forceExecution || this.financeModel.isMarketOpen()) {
context.startService(OrderService.getIntent(context));
} else {
this.orderModel.scheduleOrderServiceAlarm(this.financeModel.isMarketOpen());
}
}
@Override
public void scheduleOrderServiceAlarm() {
this.orderModel.scheduleOrderServiceAlarm(this.financeModel.isMarketOpen());
}
@Override
public void scheduleOrderServiceAlarmIfNeeded() {
List<Order> openOrders = this.getOpenOrders();
if (openOrders.size() > 0) {
this.scheduleOrderServiceAlarm();
}
}
@Override
public int purgeSnapshots(int days) {
return snapshotTotalsModel.purgeSnapshotTable(days);
}
@Override
public void createSnapshotTotals(List<Account> accounts,
LongSparseArray<List<Investment>> accountToInvestmentMap) {
Date now = new Date();
// the accounts need to be added as an atomic bundle for the sums to add up
// this loop will set the isChanged to true if any account has totals that
// are different from last snapshot
List<PerformanceItem> performanceItems = new ArrayList<>(accounts.size());
boolean isChanged = false;
for (Account account : accounts) {
List<Investment> investments = accountToInvestmentMap.get(account.getId());
if ((investments != null) && (investments.size() > 0)) {
PerformanceItem performanceItem = account.getPerformanceItem(investments, now);
performanceItems.add(performanceItem);
if (!isChanged) {
PerformanceItem lastPerformanceItem = snapshotTotalsModel.getLastSnapshot(account.getId());
if ((lastPerformanceItem == null) ||
!lastPerformanceItem.getValue().equals(performanceItem.getValue()) ||
!lastPerformanceItem.getCostBasis().equals(performanceItem.getCostBasis()) ||
!lastPerformanceItem.getTodayChange().equals(performanceItem.getTodayChange())) {
isChanged = true;
}
}
}
}
// if there is any change all accounts have to be inserted with this timestamp
if (isChanged) {
SQLiteDatabase db = sqlConnection.getWritableDatabase();
db.beginTransaction();
try {
SnapshotMapper snapshotMapper = new SnapshotMapper(true);
for (PerformanceItem performanceItem : performanceItems) {
sqlConnection.insert(snapshotMapper, performanceItem, db);
}
db.setTransactionSuccessful();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
db.endTransaction();
}
}
}
@Override
public Date getLastQuoteTime() {
return investmentModel.getLastTradeTime();
}
@Override
public List<PerformanceItem> getCurrentSnapshot() {
return snapshotTotalsModel.getCurrentSnapshot();
}
@Override
public List<PerformanceItem> getCurrentSnapshot(long accountId) {
return snapshotTotalsModel.getCurrentSnapshot(accountId);
}
@Override
public List<PerformanceItem> getCurrentDailySnapshot(int days) {
return snapshotTotalsModel.getCurrentDailySnapshot(days);
}
@Override
public List<PerformanceItem> getCurrentDailySnapshot(long accountId, int days) {
return snapshotTotalsModel.getCurrentDailySnapshot(accountId, days);
}
@Override
public OrderResult attemptExecuteOrder(Order order, Quote quote) throws OrderExecutionException {
return orderModel.attemptExecuteOrder(order, quote);
}
}