package com.ericliudeveloper.sharedbillhelper.ui.presenter;
import android.app.Activity;
import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.content.Intent;
import android.content.OperationApplicationException;
import android.net.Uri;
import android.os.RemoteException;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.ericliudeveloper.sharedbillhelper.MyApplication;
import com.ericliudeveloper.sharedbillhelper.R;
import com.ericliudeveloper.sharedbillhelper.model.Bill;
import com.ericliudeveloper.sharedbillhelper.model.Member;
import com.ericliudeveloper.sharedbillhelper.model.Payment;
import com.ericliudeveloper.sharedbillhelper.model.PaymentDAO;
import com.ericliudeveloper.sharedbillhelper.model.PaymentInfo;
import com.ericliudeveloper.sharedbillhelper.model.PaymentInfoDAO;
import com.ericliudeveloper.sharedbillhelper.provider.BillContract;
import com.ericliudeveloper.sharedbillhelper.util.CustomEvents;
import com.ericliudeveloper.sharedbillhelper.util.DigitUtils;
import com.ericliudeveloper.sharedbillhelper.util.MemberUtil;
import com.ericliudeveloper.sharedbillhelper.util.MyDateUtils;
import java.util.ArrayList;
import java.util.List;
import de.greenrobot.event.EventBus;
/**
* Created by liu on 19/06/15.
*/
public class CalculationResultPresenter {
public List<Bill> billSelections = new ArrayList(BillListPresenter.mSelection.values());
public List<Member> memberSelections = new ArrayList(MemberListPresenter.mSelection.values());
double[] memberTotalAmountArray = new double[memberSelections.size()];
CalculationResultFace mCallbacks;
static PaymentInfo mInfo;
List<Payment> mPaymentList = null;
private Activity context;
public void refreshDisplay() {
mCallbacks.showTotalAmount(String.valueOf(mInfo.getTotalAmount()));
mCallbacks.showNumberOfMembersPaying(String.valueOf(memberSelections.size()));
mCallbacks.showNumberOfBillsPaid(String.valueOf(billSelections.size()));
}
public CalculationResultPresenter(CalculationResultFace callbacks) {
mCallbacks = callbacks;
}
public void calculate() {
PaymentInfo.Builder infoBuilder = new PaymentInfo.Builder();
infoBuilder.totalAmount(getTotalAmount());
infoBuilder.numberOfMembersPaid(getNumberOfMembersPaid());
infoBuilder.numberOfBillsPaid(getNumberOfBillsPaid());
infoBuilder.paidTime(getCurrentTime());
mInfo = infoBuilder.build();
mPaymentList = new ArrayList<>();
for (Bill bill : billSelections) {
calculateMemberShareForEachBill(bill);
}
for (int i = 0; i < memberTotalAmountArray.length; i++) {
for (int j = 0; j < billSelections.size(); j++) {
memberTotalAmountArray[i] += mPaymentList.get(j * memberSelections.size() + i).getPayee_amount();
}
}
// post the event
EventBus.getDefault().postSticky(new CustomEvents.EventCalculationFinished(mPaymentList));
}
private void saveEverythingToDB() {
ArrayList<ContentProviderOperation> batch = new ArrayList<>();
// save the PaymentInfo
PaymentInfoDAO.savePaymentInfo(mInfo, null);
// do a bulk insert with the help of ContentProviderOperation
for (Payment payment : mPaymentList) {
ContentValues values = PaymentDAO.getContentValuesFromPaymentInstance(payment);
Uri uri = BillContract.Payments.CONTENT_URI;
ContentProviderOperation operation = ContentProviderOperation.newInsert(uri).withValues(values).build();
batch.add(operation);
}
try {
MyApplication.getAppContentResolver().applyBatch(BillContract.CONTENT_AUTHORITY, batch);
} catch (RemoteException e) {
e.printStackTrace();
} catch (OperationApplicationException e) {
e.printStackTrace();
}
}
/**
* calculate how much money each member should pay for this bill
* and other necessary info
*
* @param bill
*/
private void calculateMemberShareForEachBill(Bill bill) {
double amount = bill.getAmount();
// an Array to store the days each member is eligible for this bill
int[] memberPayingDayArray = new int[memberSelections.size()];
// an Array to store each member's start paying date for this bill
String[] payeeStartDateArray = new String[memberSelections.size()];
// an Array to store each member's end paying date for this bill
String[] payeeEndDateArray = new String[memberSelections.size()];
int index = 0;
for (Member member : memberSelections) {
int payingDaysForThisBill = MyDateUtils.calculateMemberPayingDays(member.getMoveInDate()
, member.getMoveOutDate()
, bill.getStartDate()
, bill.getEndDate());
String[] payeeStartEndDateArray = MyDateUtils.getPayeeStartEndDates(
member.getMoveInDate()
, member.getMoveOutDate()
, bill.getStartDate()
, bill.getEndDate()
);
if (payeeStartEndDateArray != null) {
payeeStartDateArray[index] = payeeStartEndDateArray[0];
payeeEndDateArray[index] = payeeStartEndDateArray[1];
}
if (payingDaysForThisBill > 0) {
memberPayingDayArray[index] = payingDaysForThisBill;
}
index++;
}
// an Array to store how much money for each member to pay for this bill
double[] memberShareArray = new double[memberSelections.size()];
// sum all all days all members have been in this bill
double totalNumOfDays = 0d;
for (int num : memberPayingDayArray) {
totalNumOfDays += num;
}
for (int i = 0; i < memberShareArray.length; i++) {
if (totalNumOfDays > 0) {
memberShareArray[i] = amount * memberPayingDayArray[i] / totalNumOfDays;
} else {
memberShareArray[i] = 0d;
}
}
Member member1 = null; // avoid creating instances in a loop
for (int i = 0; i < memberSelections.size(); i++) {
member1 = memberSelections.get(i);
Payment.Builder paymentBuilder = new Payment.Builder(mInfo.getSerialNumber(), bill.getId(), member1.getId());
int payeeDays = memberPayingDayArray[i];
paymentBuilder.payeeDays(payeeDays);
double payeeAmount = memberShareArray[i];
paymentBuilder.payee_amount(payeeAmount);
String payeeStartDate = payeeStartDateArray[i];
if (!TextUtils.isEmpty(payeeStartDate)) {
paymentBuilder.payeeStartDate(payeeStartDate);
}
String payeeEndDate = payeeEndDateArray[i];
if (!TextUtils.isEmpty(payeeEndDate)) {
paymentBuilder.payeeEndDate(payeeEndDate);
}
mPaymentList.add(paymentBuilder.build());
}
}
private String getCurrentTime() {
return MyDateUtils.getCurrentTimeString();
}
private int getNumberOfBillsPaid() {
return billSelections.size();
}
private int getNumberOfMembersPaid() {
return memberSelections.size();
}
private double getTotalAmount() {
double totalAmount = 0d;
for (Bill bill : billSelections) {
totalAmount += bill.getAmount();
}
return totalAmount;
}
public RecyclerView.ViewHolder createViewHolder(ViewGroup parent, int viewType) {
View rowLayout = LayoutInflater.from(parent.getContext()).inflate(R.layout.payment_row, parent, false);
return new MemberPaymentViewHolder(rowLayout);
}
public void bindViewHolder(RecyclerView.ViewHolder holder, int position) {
((MemberPaymentViewHolder) holder).setItemData(memberSelections.get(position), memberTotalAmountArray[position]);
}
public int getItemCount() {
return memberSelections.size();
}
public void startActionSend() {
Intent smsIntent = new Intent(Intent.ACTION_SEND);
smsIntent.putExtra(Intent.EXTRA_TEXT, composeSMS());
if (smsIntent.resolveActivity(context.getPackageManager()) != null) {
mCallbacks.startActivity(smsIntent);
}
}
private String composeSMS() {
StringBuilder builder = new StringBuilder();
builder.append("Total ");
builder.append(billSelections.size());
builder.append(" bills need to pay. ");
Member member = null;
double amount;
for (int i = 0; i < memberSelections.size(); i++) {
member = memberSelections.get(i);
amount = memberTotalAmountArray[i];
builder.append(member.getFirstName());
if (!TextUtils.isEmpty(member.getLastName())) {
builder.append(" " +member.getLastName());
}
builder.append(" " +DigitUtils.convertToDollarFormat(amount) + "; ");
}
return builder.toString();
}
public void setContext(Activity context) {
this.context = context;
}
public interface CalculationResultFace {
void showTotalAmount(String amount);
void showNumberOfMembersPaying(String numMembers);
void showNumberOfBillsPaid(String numBills);
void startActivity(Intent intent);
}
public static class MemberPaymentViewHolder extends RecyclerView.ViewHolder {
private TextView tvPayeeFullName, tvPercentage;
private ProgressBar pbPercentage;
private TextView tvPayeeAmount;
public MemberPaymentViewHolder(View itemview) {
super(itemview);
tvPayeeFullName = (TextView) itemview
.findViewById(R.id.tvPayeeFullName);
tvPercentage = (TextView) itemview
.findViewById(R.id.tvPercentage);
pbPercentage = (ProgressBar) itemview
.findViewById(R.id.pbPercentage);
tvPayeeAmount = (TextView) itemview
.findViewById(R.id.tvPayeeAmout);
}
public void setItemData(Member member, double amount) {
String payeeFullName = MemberUtil.getFullNameString(member);
tvPayeeFullName.setText(payeeFullName);
String amountString = DigitUtils.convertToDollarFormat(amount);
tvPayeeAmount.setText(amountString);
if (mInfo != null) {
int percentage = (int) (100 * amount / mInfo.getTotalAmount());
String percentageHint = String.valueOf(percentage) + "%";
tvPercentage.setHint(percentageHint);
pbPercentage.setProgress(percentage);
}
}
}
}