package co.smartreceipts.android.model.impl.columns.receipts;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
import co.smartreceipts.android.R;
import co.smartreceipts.android.model.Column;
import co.smartreceipts.android.model.ColumnDefinitions;
import co.smartreceipts.android.model.Receipt;
import co.smartreceipts.android.model.comparators.ColumnNameComparator;
import co.smartreceipts.android.model.impl.columns.AbstractColumnImpl;
import co.smartreceipts.android.model.impl.columns.BlankColumn;
import co.smartreceipts.android.model.impl.columns.SettingUserIdColumn;
import co.smartreceipts.android.settings.UserPreferenceManager;
import co.smartreceipts.android.sync.model.SyncState;
import co.smartreceipts.android.sync.model.impl.DefaultSyncState;
import wb.android.flex.Flex;
/**
* Provides specific definitions for all {@link co.smartreceipts.android.model.Receipt} {@link co.smartreceipts.android.model.Column}
* objects
*/
public final class ReceiptColumnDefinitions implements ColumnDefinitions<Receipt> {
private enum ActualDefinition {
BLANK(R.string.column_item_blank),
CATEGORY_CODE(R.string.column_item_category_code),
CATEGORY_NAME(R.string.column_item_category_name),
USER_ID(R.string.column_item_user_id),
REPORT_NAME(R.string.column_item_report_name),
REPORT_START_DATE(R.string.column_item_report_start_date),
REPORT_END_DATE(R.string.column_item_report_end_date),
REPORT_COMMENT(R.string.column_item_report_comment),
REPORT_COST_CENTER(R.string.column_item_report_cost_center),
IMAGE_FILE_NAME(R.string.column_item_image_file_name),
IMAGE_PATH(R.string.column_item_image_path),
COMMENT(R.string.RECEIPTMENU_FIELD_COMMENT),
CURRENCY(R.string.RECEIPTMENU_FIELD_CURRENCY),
DATE(R.string.RECEIPTMENU_FIELD_DATE),
NAME(R.string.RECEIPTMENU_FIELD_NAME),
PRICE(R.string.RECEIPTMENU_FIELD_PRICE),
PRICE_EXCHANGED(R.string.column_item_converted_price_exchange_rate),
TAX(R.string.RECEIPTMENU_FIELD_TAX),
TAX_EXCHANGED(R.string.column_item_converted_tax_exchange_rate),
PRICE_PLUS_TAX_EXCHANGED(R.string.column_item_converted_price_plus_tax_exchange_rate),
EXCHANGE_RATE(R.string.column_item_exchange_rate),
PICTURED(R.string.column_item_pictured),
REIMBURSABLE(R.string.column_item_reimbursable, R.string.column_item_deprecated_expensable),
INDEX(R.string.column_item_index),
ID(R.string.column_item_id),
PAYMENT_METHOD(R.string.column_item_payment_method),
EXTRA_EDITTEXT_1(R.string.RECEIPTMENU_FIELD_EXTRA_EDITTEXT_1),
EXTRA_EDITTEXT_2(R.string.RECEIPTMENU_FIELD_EXTRA_EDITTEXT_2),
EXTRA_EDITTEXT_3(R.string.RECEIPTMENU_FIELD_EXTRA_EDITTEXT_3);
private final int mStringResId;
private final int mLegacyStringResId;
ActualDefinition(@StringRes int stringResId) {
this(stringResId, -1);
}
/**
* Allows us to specify a legacy item that we've updated our name from, since columns are keyed off the name itself (so what happens
* if we change the column name... probably not the best design here but we'll revisit later)
*
* @param stringResId the current id
* @param legacyStringResId the legacy id
*/
ActualDefinition(@StringRes int stringResId, @StringRes int legacyStringResId) {
mStringResId = stringResId;
mLegacyStringResId = legacyStringResId;
}
@StringRes
public final int getStringResId() {
return mStringResId;
}
@StringRes
public final int getLegacyStringResId() {
return mLegacyStringResId;
}
}
@Inject Context context;
@Inject UserPreferenceManager mPreferences;
@Inject Flex flex;
private final ActualDefinition[] mActualDefinitions = ActualDefinition.values();
@Inject
public ReceiptColumnDefinitions() {
}
@Nullable
@Override
public Column<Receipt> getColumn(int id, @NonNull String definitionName, @NonNull SyncState syncState) {
for (int i = 0; i < mActualDefinitions.length; i++) {
final ActualDefinition definition = mActualDefinitions[i];
if (definitionName.equals(getColumnNameFromStringResId(definition.getStringResId()))) {
return getColumnFromClass(id, definition, definitionName, syncState);
} else if (definition.getLegacyStringResId() >= 0 && definitionName.equals(getColumnNameFromStringResId(definition.getLegacyStringResId()))) {
final String newDefinitionName = getColumnNameFromStringResId(definition.getStringResId());
return getColumnFromClass(id, definition, newDefinitionName, syncState);
}
}
return null;
}
@NonNull
@Override
public List<Column<Receipt>> getAllColumns() {
final ArrayList<AbstractColumnImpl<Receipt>> columns = new ArrayList<>(mActualDefinitions.length);
for (int i = 0; i < mActualDefinitions.length; i++) {
final ActualDefinition definition = mActualDefinitions[i];
final AbstractColumnImpl<Receipt> column = getColumnFromClass(Column.UNKNOWN_ID, definition, getColumnNameFromStringResId(definition.getStringResId()), new DefaultSyncState());
if (column != null) {
columns.add(column);
}
}
Collections.sort(columns, new ColumnNameComparator<AbstractColumnImpl<Receipt>>());
return new ArrayList<Column<Receipt>>(columns);
}
@NonNull
@Override
public Column<Receipt> getDefaultInsertColumn() {
return new BlankColumn<>(Column.UNKNOWN_ID, getColumnNameFromStringResId(ActualDefinition.BLANK.getStringResId()), new DefaultSyncState());
}
public List<Column<Receipt>> getCsvDefaults() {
// TODO: Re-design how these are added
final ArrayList<Column<Receipt>> columns = new ArrayList<>();
columns.add(getColumn(ActualDefinition.CATEGORY_CODE));
columns.add(getColumn(ActualDefinition.NAME));
columns.add(getColumn(ActualDefinition.PRICE));
columns.add(getColumn(ActualDefinition.CURRENCY));
columns.add(getColumn(ActualDefinition.DATE));
return columns;
}
public List<Column<Receipt>> getPdfDefaults() {
// TODO: Re-design how these are added
final ArrayList<Column<Receipt>> columns = new ArrayList<>();
columns.add(getColumn(ActualDefinition.NAME));
columns.add(getColumn(ActualDefinition.PRICE));
columns.add(getColumn(ActualDefinition.DATE));
columns.add(getColumn(ActualDefinition.CATEGORY_NAME));
columns.add(getColumn(ActualDefinition.REIMBURSABLE));
columns.add(getColumn(ActualDefinition.PICTURED));
return columns;
}
private Column<Receipt> getColumn(@NonNull ActualDefinition actualDefinition) {
return getColumnFromClass(Column.UNKNOWN_ID, actualDefinition, getColumnNameFromStringResId(actualDefinition.getStringResId()), new DefaultSyncState());
}
@Nullable
private AbstractColumnImpl<Receipt> getColumnFromClass(int id, @NonNull ActualDefinition definition, @NonNull String definitionName, @NonNull SyncState syncState) {
if (TextUtils.isEmpty(definitionName)) {
// Exit early if we have no name (i.e. it's an undefined extra)
return null;
}
switch (definition) {
case BLANK:
return new BlankColumn<>(id, definitionName, syncState);
case CATEGORY_CODE:
return new ReceiptCategoryCodeColumn(id, definitionName, syncState);
case CATEGORY_NAME:
return new ReceiptCategoryNameColumn(id, definitionName, syncState);
case USER_ID:
return new SettingUserIdColumn<>(id, definitionName, syncState, mPreferences);
case REPORT_NAME:
return new ReportNameColumn(id, definitionName, syncState);
case REPORT_START_DATE:
return new ReportStartDateColumn(id, definitionName, syncState, context, mPreferences);
case REPORT_END_DATE:
return new ReportEndDateColumn(id, definitionName, syncState, context, mPreferences);
case REPORT_COMMENT:
return new ReportCommentColumn(id, definitionName, syncState);
case REPORT_COST_CENTER:
return new ReportCostCenterColumn(id, definitionName, syncState);
case IMAGE_FILE_NAME:
return new ReceiptFileNameColumn(id, definitionName, syncState);
case IMAGE_PATH:
return new ReceiptFilePathColumn(id, definitionName, syncState);
case COMMENT:
return new ReceiptCommentColumn(id, definitionName, syncState);
case CURRENCY:
return new ReceiptCurrencyCodeColumn(id, definitionName, syncState);
case DATE:
return new ReceiptDateColumn(id, definitionName, syncState, context, mPreferences);
case NAME:
return new ReceiptNameColumn(id, definitionName, syncState);
case PRICE:
return new ReceiptPriceColumn(id, definitionName, syncState);
case PRICE_EXCHANGED:
return new ReceiptExchangedPriceColumn(id, definitionName, syncState, context);
case TAX:
return new ReceiptTaxColumn(id, definitionName, syncState);
case TAX_EXCHANGED:
return new ReceiptExchangedTaxColumn(id, definitionName, syncState, context);
case PRICE_PLUS_TAX_EXCHANGED:
return new ReceiptNetExchangedPricePlusTaxColumn(id, definitionName, syncState, context, mPreferences);
case EXCHANGE_RATE:
return new ReceiptExchangeRateColumn(id, definitionName, syncState);
case PICTURED:
return new ReceiptIsPicturedColumn(id, definitionName, syncState, context);
case REIMBURSABLE:
return new ReceiptIsReimbursableColumn(id, definitionName, syncState, context);
case INDEX:
return new ReceiptIndexColumn(id, definitionName, syncState);
case ID:
return new ReceiptIdColumn(id, definitionName, syncState);
case PAYMENT_METHOD:
return new ReceiptPaymentMethodColumn(id, definitionName, syncState);
case EXTRA_EDITTEXT_1:
return new ReceiptExtra1Column(id, definitionName, syncState);
case EXTRA_EDITTEXT_2:
return new ReceiptExtra2Column(id, definitionName, syncState);
case EXTRA_EDITTEXT_3:
return new ReceiptExtra3Column(id, definitionName, syncState);
default:
throw new IllegalArgumentException("Unknown definition type: " + definition);
}
}
private String getColumnNameFromStringResId(int stringResId) {
if (flex != null) {
return flex.getString(context, stringResId);
} else {
return context.getString(stringResId);
}
}
}