/*
* Licensed Materials - Property of IBM
* © Copyright IBM Corporation 2015. All Rights Reserved.
*/
package com.ibm.mil.readyapps.telco.cycles;
import android.content.Context;
import android.content.res.Resources;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.ibm.mil.readyapps.telco.R;
import com.ibm.mil.readyapps.telco.baseplan.BasePlanModelImpl;
import com.ibm.mil.readyapps.telco.utils.PlanConstants;
import com.ibm.mil.readyapps.telco.views.RobotoTextView;
import com.yqritc.recyclerviewmultipleviewtypesadapter.DataBindAdapter;
import com.yqritc.recyclerviewmultipleviewtypesadapter.DataBinder;
import java.text.DecimalFormat;
import java.util.Locale;
import butterknife.Bind;
import butterknife.ButterKnife;
/**
* Binder to append the user data/talk/text cycle information
* to the corresponding recyclerView ViewHolder
*/
public class CycleBinder extends DataBinder<CycleBinder.CurrentCycleViewHolder> {
private Cycle currentCycle;
private final CoordinatorLayout snackbar_layout;
private final Resources resources;
private int DOLLARS_PER_STEP;
private int STEP_AMOUNT;
private int MAX_AMOUNT;
private final BasePlanModelImpl basePlanModel;
private final CycleModelImpl cycleModel = new CycleModelImpl();
/**
* Constructor to initialize the cycle binder
*
* @param adapter the adapter that uses this binder to populate the recyclerView
* @param layout coordinator layout from the main activity
* used for inflating the snackBar
* @param context context from the main activity
* used to access application resources
*/
public CycleBinder(DataBindAdapter adapter, CoordinatorLayout layout, Context context) {
super(adapter);
this.snackbar_layout = layout;
resources = context.getResources();
this.basePlanModel = new BasePlanModelImpl();
}
/**
* creates a new ViewHolder using the provided xml layout
*
* @param viewGroup the parent ViewGroup that this ViewHolder will inflate
* specifies the xml layout that the binder should use to create the view
* @return the inflated view
*/
@Override
public CurrentCycleViewHolder newViewHolder(ViewGroup viewGroup) {
View currentCycleView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.data_current_cycle, viewGroup, false);
return new CurrentCycleViewHolder(currentCycleView);
}
/**
* @param viewHolder the ViewHolder to use onBind
* has all the associated views in this layout
* @param position the position of this ViewHolder in the binder
*/
@Override
public void bindViewHolder(CurrentCycleViewHolder viewHolder, int position) {
float usedPercent = ((currentCycle.getUsed() * 100) / currentCycle.getLimit());
DecimalFormat df ;
if(Locale.getDefault().toString().equals("en_US")){
df = new DecimalFormat("#.##");
}
else{
df = new DecimalFormat("#,##");
}
usedPercent = (float)Float.valueOf(df.format(usedPercent));
viewHolder.usageImage.setImageResource(currentCycle.getCycleImage());
viewHolder.usageBottomLeftUsage.setText(currentCycle.getUsed() + "/" + currentCycle.getLimit() + " " + currentCycle.getUnit());
viewHolder.usageBottomRightText.setText(usedPercent + resources.getString(R.string.percent_used));
viewHolder.usageProgressBar.setProgress((int)usedPercent);
viewHolder.monthlyDataUsage.setText(currentCycle.getLimit() + "");
viewHolder.unit.setText(currentCycle.getUnit());
}
/**
* Get the item count for the CycleBinder
*
* @return the number of items/layouts in the ViewHolder
*/
@Override
public int getItemCount() {
return 1;
}
/**
* Update the current cycle and set constants for this cycle instance
*
* @param cycle the updated cycle instance (data/talk/text)
*/
public void add(Cycle cycle) {
currentCycle = cycle;
DOLLARS_PER_STEP = getDollarsPerStep();
STEP_AMOUNT = getStepAmount();
MAX_AMOUNT = getMaxAmount();
notifyBinderDataSetChanged();
}
/**
* Get the step amount from PlanConstants based on the current cycle type
*
* @return the step amount for the current cycle
*/
private int getStepAmount() {
switch (currentCycle.getType()) {
case PlanConstants.DATA:
return PlanConstants.DATA_STEP_AMOUNT;
case PlanConstants.TALK:
return PlanConstants.TALK_STEP_AMOUNT;
case PlanConstants.TEXT:
return PlanConstants.TEXT_STEP_AMOUNT;
}
return 0;
}
/**
* Get the monetary unit the from PlanConstants based on the current cycle type
* Note: this is not necessarily in dollars, the amount will be in whichever
* monetary unit the user is using
* @return the step amount for the current cycle
*/
private int getDollarsPerStep() {
switch (currentCycle.getType()) {
case PlanConstants.DATA:
return PlanConstants.DATA_DOLLARS_PER_STEP;
case PlanConstants.TALK:
return PlanConstants.TALK_DOLLARS_PER_STEP;
case PlanConstants.TEXT:
return PlanConstants.TEXT_DOLLARS_PER_STEP;
}
return 0;
}
/**
* Get the maximum allowed limit amount from PlanConstants
*
* @return the maximum limit amount for the current cycle
*/
private int getMaxAmount() {
switch (currentCycle.getType()) {
case PlanConstants.DATA:
return PlanConstants.DATA_MAX_AMOUNT;
case PlanConstants.TALK:
return PlanConstants.TALK_MAX_AMOUNT;
case PlanConstants.TEXT:
return PlanConstants.TEXT_MAX_AMOUNT;
}
return 0;
}
/**
* Update the navigation bar to
* reflect the base plan changes
*
* @param addedCost the amount needed to be added to the baseCost
*/
private void updateBasePlan(int addedCost) {
basePlanModel.updateBaseCost(addedCost);
}
/**
* Define the CurrentCycleViewHolder
* bind views that need to be updated in the ViewHolder onBind
*/
public class CurrentCycleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
@Bind(R.id.usage_image) ImageView usageImage;
@Bind(R.id.bottom_left_text) RobotoTextView usageBottomLeftUsage;
@Bind(R.id.bottom_right_text) RobotoTextView usageBottomRightText;
@Bind(R.id.progress_bar) ProgressBar usageProgressBar;
@Bind(R.id.usage_gb) RobotoTextView monthlyDataUsage;
@Bind(R.id.up_arrow) ImageView upArrow;
@Bind(R.id.down_arrow) ImageView downArrow;
@Bind(R.id.confirm) RobotoTextView confirmUpdate;
@Bind(R.id.usage_unit) RobotoTextView unit;
private int prevLimit = 0;
public CurrentCycleViewHolder(View currentCycleView) {
super(currentCycleView);
ButterKnife.bind(this, currentCycleView);
upArrow.setOnClickListener(this);
downArrow.setOnClickListener(this);
confirmUpdate.setOnClickListener(this);
}
/**
* On click listener for the action buttons in the current cycle (up/down arrow, accept)
*
* @param view the view that was clicked
*/
@Override
public void onClick(View view) {
int limit = Integer.parseInt(monthlyDataUsage.getText().toString());
prevLimit = currentCycle.getLimit();
if (view.equals(upArrow) && limit < MAX_AMOUNT) {
limit = limit + STEP_AMOUNT;
//change accept button color based on the selected amount
if (limit == prevLimit)
confirmUpdate.setTextColor(resources.getColor(R.color.light_gray));
else
confirmUpdate.setTextColor(resources.getColor(R.color.light_indigo));
} else if (view.equals(downArrow) && limit > currentCycle.getUsed() && limit > PlanConstants.MIN_UNIT) {
limit = limit - STEP_AMOUNT;
//change accept button color based on the selected amount
if (limit == prevLimit)
confirmUpdate.setTextColor(resources.getColor(R.color.light_gray));
else
confirmUpdate.setTextColor(resources.getColor(R.color.light_indigo));
} else if (view.equals(confirmUpdate) && limit != prevLimit) {
updateLimit(limit);
//also update the monthly cost in the navigation bar
int addedCost = (limit - prevLimit) / STEP_AMOUNT * DOLLARS_PER_STEP;
updateBasePlan(addedCost);
createSnackBar(addedCost);
}
monthlyDataUsage.setText(limit + "");
}
/**
* Update the limit of the specific cycle type
* update the corresponding views
*
* @param limit the new limit amount to update to
*/
private void updateLimit(int limit) {
currentCycle.setLimit(limit);
updatePlanCycles();
confirmUpdate.setTextColor(resources.getColor(R.color.light_gray));
}
/**
* create a SnackBar after changing base plan
* the user gets ability to undo the plan change
*
* @param addedCost the amount added/removed after plan change
* used to undo the plan change
*/
private void createSnackBar(final int addedCost) {
View.OnClickListener undoAction;
/**
* on click listener for undo of base plan change
*/
undoAction = new View.OnClickListener() {
//click listener for the SnackBar undo
@Override
public void onClick(View view) {
updateLimit(prevLimit);
basePlanModel.updateBaseCost(-addedCost);
}
};
//build the SnackBar and display it
Snackbar.make(snackbar_layout, resources.getString(R.string.baseplan_snackbar), Snackbar.LENGTH_LONG)
.setAction(resources.getString(R.string.undo), undoAction)
.setActionTextColor(resources.getColor(R.color.light_indigo))
.show();
}
}
/**
* pass the current cycle to the corresponding data/talk/text presenter
*/
private void updatePlanCycles() {
switch (currentCycle.getType()) {
case PlanConstants.DATA:
cycleModel.updateDataCycle(currentCycle);
break;
case PlanConstants.TALK:
cycleModel.updateTalkCycle(currentCycle);
break;
case PlanConstants.TEXT:
cycleModel.updateTextCycle(currentCycle);
break;
}
}
}