package ru.orangesoftware.financisto2.export.qif;
import android.database.Cursor;
import android.support.v4.util.LongSparseArray;
import ru.orangesoftware.financisto2.model.Account;
import ru.orangesoftware.financisto2.model.Category;
import ru.orangesoftware.financisto2.model.Transaction;
import ru.orangesoftware.financisto2.utils.Utils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import static ru.orangesoftware.financisto2.db.DatabaseHelper.BlotterColumns;
import static ru.orangesoftware.financisto2.export.qif.QifUtils.*;
/**
* Created by IntelliJ IDEA.
* User: Denis Solonenko
* Date: 2/8/11 12:52 AM
*/
public class QifTransaction {
public long id;
public Date date;
public long amount;
public String payee;
public String memo;
public String category;
public String categoryClass;
public String toAccount;
public String project;
public boolean isSplit = false;
public List<QifTransaction> splits;
public static QifTransaction fromBlotterCursor(Cursor c, LongSparseArray<Category> categoriesMap) {
QifTransaction t = new QifTransaction();
t.id = c.getLong(BlotterColumns._id.ordinal());
t.date = new Date(c.getLong(BlotterColumns.datetime.ordinal()));
t.amount = c.getLong(BlotterColumns.from_amount.ordinal());
t.payee = c.getString(BlotterColumns.payee.ordinal());
t.memo = c.getString(BlotterColumns.note.ordinal());
long projectId = c.getLong(BlotterColumns.project_id.ordinal());
if (projectId > 0) {
t.project = c.getString(BlotterColumns.project.ordinal());
}
Category category = getCategoryFromCursor(c, categoriesMap);
if (category != null) {
QifCategory qifCategory = QifCategory.fromCategory(category);
t.category = qifCategory.name;
}
t.isSplit = categoryIsSplit(c);
t.toAccount = c.getString(BlotterColumns.to_account_title.ordinal());
return t;
}
private static Category getCategoryFromCursor(Cursor c, LongSparseArray<Category> categoriesMap) {
long categoryId = c.getLong(BlotterColumns.category_id.ordinal());
return categoriesMap.get(categoryId);
}
private static boolean categoryIsSplit(Cursor c) {
long categoryId = c.getLong(BlotterColumns.category_id.ordinal());
return categoryId == Category.SPLIT_CATEGORY_ID;
}
public void writeTo(QifBufferedWriter qifWriter, QifExportOptions options)
throws IOException {
qifWriter.write("D").write(options.dateFormat.format(date)).newLine();
qifWriter.write("T").write(Utils.amountToString(options.currency, amount)).newLine();
if (toAccount != null) {
qifWriter.write("L[").write(toAccount).write("]").newLine();
} else if (category != null && project != null) {
qifWriter.write("L").write(category).write("/").write(project).newLine();
} else if (category != null) {
qifWriter.write("L").write(category).newLine();
} else if (project != null) {
qifWriter.write("L/").write(project).newLine();
}
if (Utils.isNotEmpty(payee)) {
qifWriter.write("P").write(payee).newLine();
}
if (Utils.isNotEmpty(memo)) {
qifWriter.write("M").write(memo).newLine();
}
if (isSplit()) {
for (QifTransaction split : splits) {
writeSplit(qifWriter, options, split);
}
}
qifWriter.end();
}
private void writeSplit(QifBufferedWriter qifWriter, QifExportOptions options, QifTransaction split) throws IOException {
if (split.toAccount != null) {
qifWriter.write("S[").write(split.toAccount).write("]").newLine();
} else {
if (split.category != null) {
qifWriter.write("S").write(split.category).newLine();
} else {
qifWriter.write("SNo category").newLine();
}
}
qifWriter.write("$").write(Utils.amountToString(options.currency, split.amount)).newLine();
if (Utils.isNotEmpty(split.memo)) {
qifWriter.write("E").write(split.memo).newLine();
}
}
public boolean isSplit() {
return isSplit;
}
public void setSplits(List<QifTransaction> splits) {
this.splits = splits;
}
public void readFrom(QifBufferedReader r, QifDateFormat dateFormat) throws IOException {
QifTransaction split = null;
String line;
while ((line = r.readLine()) != null) {
if (line.startsWith("^")) {
break;
}
if (line.startsWith("D")) {
this.date = parseDate(trimFirstChar(line), dateFormat);
} else if (line.startsWith("T")) {
this.amount = parseMoney(trimFirstChar(line));
} else if (line.startsWith("P")) {
this.payee = trimFirstChar(line);
} else if (line.startsWith("M")) {
this.memo = trimFirstChar(line);
} else if (line.startsWith("L")) {
parseCategory(this, line);
} else if (line.startsWith("S")) {
addSplit(split);
split = new QifTransaction();
parseCategory(split, line);
} else if (line.startsWith("$")) {
if (split != null) {
split.amount = parseMoney(trimFirstChar(line));
}
} else if (line.startsWith("E")) {
if (split != null) {
split.memo = trimFirstChar(line);
}
}
}
addSplit(split);
adjustSplitsDatetime();
}
private void adjustSplitsDatetime() {
if (splits != null) {
for (QifTransaction split : splits) {
split.date = this.date;
}
}
}
private void parseCategory(QifTransaction t, String line) {
String category = trimFirstChar(line);
int i = category.indexOf('/');
if (i != -1) {
t.categoryClass = category.substring(i+1);
category = category.substring(0, i);
}
if (isTransferCategory(category)) {
t.toAccount = category.substring(1, category.length()-1);
} else {
t.category = category;
}
}
private void addSplit(QifTransaction split) {
if (split == null) {
return;
}
if (splits == null) {
splits = new ArrayList<QifTransaction>();
}
splits.add(split);
}
public static QifTransaction fromTransaction(Transaction transaction, LongSparseArray<Category> categoriesMap, LongSparseArray<Account> accountsMap) {
QifTransaction qifTransaction = new QifTransaction();
qifTransaction.amount = transaction.fromAmount;
qifTransaction.memo = transaction.note;
if (transaction.toAccountId > 0) {
Account toAccount = accountsMap.get(transaction.toAccountId);
qifTransaction.toAccount = toAccount.title;
//TODO: test if from and to accounts have different currencies
}
Category category = categoriesMap.get(transaction.categoryId);
if (category != null) {
QifCategory qifCategory = QifCategory.fromCategory(category);
qifTransaction.category = qifCategory.name;
}
qifTransaction.isSplit = transaction.isSplitParent();
return qifTransaction;
}
public Transaction toTransaction() {
Transaction t = new Transaction();
t.id = -1;
t.dateTime = date.getTime();
t.fromAmount = amount;
t.note = memo;
return t;
}
public boolean isTransfer() {
return toAccount != null;
}
}