/*
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.mobile.activities.lastviewedpatients;
import android.app.Activity;
import android.support.v7.widget.RecyclerView;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.openmrs.mobile.R;
import org.openmrs.mobile.api.retrofit.PatientApi;
import org.openmrs.mobile.api.retrofit.VisitApi;
import org.openmrs.mobile.dao.PatientDAO;
import org.openmrs.mobile.listeners.retrofit.DownloadPatientCallbackListener;
import org.openmrs.mobile.models.Patient;
import org.openmrs.mobile.utilities.DateUtils;
import org.openmrs.mobile.utilities.FontsUtil;
import org.openmrs.mobile.utilities.ToastUtil;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import rx.android.schedulers.AndroidSchedulers;
class LastViewedPatientRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int VIEW_TYPE_ITEM = 0;
private final int VIEW_TYPE_LOADING = 1;
private Activity mContext;
private List<Patient> patients;
private Set<Integer> selectedPatientPositions;
private boolean isAllSelected = false;
private boolean isLongClicked = false;
private boolean enableDownload = true;
private ActionMode actionMode;
private LastViewedPatientsContract.View view;
LastViewedPatientRecyclerViewAdapter(Activity context, List<Patient> items, LastViewedPatientsContract.View view) {
this.mContext = context;
this.patients = items;
this.selectedPatientPositions = new HashSet<>();
this.view = view;
}
public List<Patient> getPatients() {
return patients;
}
public Set<Integer> getSelectedPatientPositions() {
return selectedPatientPositions;
}
public void setSelectedPatientPositions(Set<Integer> selectedPatientPositions) {
this.selectedPatientPositions = selectedPatientPositions;
}
public void addPatients(List<Patient> patients){
this.patients.addAll(patients);
notifyDataSetChanged();
}
public void deleteLastItem(){
patients.remove(getItemCount()-1);
notifyItemRemoved(getItemCount());
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if( viewType == VIEW_TYPE_ITEM ) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.find_last_viewed_patients_row, parent, false);
FontsUtil.setFont((ViewGroup) itemView);
return new PatientViewHolder(itemView);
} else {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.progressbar_item, parent, false);
FontsUtil.setFont((ViewGroup) itemView);
return new ProgressBarViewHolder(itemView);
}
}
@Override
public int getItemViewType(int position) {
return patients.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof PatientViewHolder) {
final Patient patient = patients.get(position);
((PatientViewHolder) holder).setSelected(isPatientSelected(position));
if (null != patient.getIdentifier()) {
String patientIdentifier = String.format(mContext.getResources().getString(R.string.patient_identifier),
patient.getIdentifier().getIdentifier());
((PatientViewHolder) holder).mIdentifier.setText(patientIdentifier);
}
if (null != patient.getPerson().getName()) {
((PatientViewHolder) holder).mDisplayName.setText(patient.getPerson().getName().getNameString());
}
if (null != patient.getPerson().getGender()) {
((PatientViewHolder) holder).mGender.setText(patient.getPerson().getGender());
}
try {
((PatientViewHolder) holder).mBirthDate.setText(DateUtils.convertTime(DateUtils.convertTime(patient.getPerson().getBirthdate())));
} catch (Exception e) {
((PatientViewHolder) holder).mBirthDate.setText(" ");
}
if (null != ((PatientViewHolder) holder).mAvailableOfflineCheckbox) {
setUpCheckBoxLogic( ((PatientViewHolder) holder), patient);
}
} else {
((ProgressBarViewHolder) holder).progressBar.setIndeterminate(true);
}
}
private boolean isPatientSelected(int position) {
for (Integer selectedPatientPosition : selectedPatientPositions) {
if(selectedPatientPosition.equals(position)){
return true;
}
}
return false;
}
@Override
public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) {
if (holder instanceof PatientViewHolder) {
((PatientViewHolder) holder).clearAnimation();
}
}
@Override
public int getItemCount() {
return patients == null ? 0 : patients.size();
}
class PatientViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener{
private LinearLayout mRowLayout;
private TextView mIdentifier;
private TextView mDisplayName;
private TextView mGender;
private TextView mBirthDate;
private CheckBox mAvailableOfflineCheckbox;
public PatientViewHolder(View itemView) {
super(itemView);
mRowLayout = (LinearLayout) itemView;
mIdentifier = (TextView) itemView.findViewById(R.id.lastViewedPatientIdentifier);
mDisplayName = (TextView) itemView.findViewById(R.id.lastViewedPatientDisplayName);
mGender = (TextView) itemView.findViewById(R.id.lastViewedPatientGender);
mBirthDate = (TextView) itemView.findViewById(R.id.lastViewedPatientBirthDate);
mAvailableOfflineCheckbox = (CheckBox) itemView.findViewById(R.id.offlineCheckbox);
mRowLayout.setOnClickListener(this);
mRowLayout.setOnLongClickListener(this);
}
public void clearAnimation() {
mRowLayout.clearAnimation();
}
@Override
public void onClick(View view) {
if(isLongClicked){
setSelected(!mRowLayout.isSelected());
}
}
private void setSelected(boolean select) {
if(select){
if (!enableDownload)
toggleDownloadButton();
selectedPatientPositions.add(getAdapterPosition());
this.mRowLayout.setSelected(true);
} else {
removeIdFromSelectedIds(getAdapterPosition());
this.mRowLayout.setSelected(false);
}
}
@Override
public boolean onLongClick(View v) {
if (v.isSelected()) {
setSelected(false);
} else {
if (!isLongClicked) {
startActionMode();
}
isLongClicked = true;
setSelected(true);
notifyDataSetChanged();
}
return true;
}
}
class ProgressBarViewHolder extends RecyclerView.ViewHolder {
private ProgressBar progressBar;
public ProgressBarViewHolder(View itemView) {
super(itemView);
progressBar = (ProgressBar)itemView.findViewById(R.id.recycleviewProgressbar);
}
}
private void removeIdFromSelectedIds(Integer position) {
Set<Integer> newSet = new HashSet<>();
for (Integer selectedPatientsId : selectedPatientPositions) {
if(!selectedPatientsId.equals(position)){
newSet.add(selectedPatientsId);
}
}
selectedPatientPositions = newSet;
if (selectedPatientPositions.size() == 0 && isLongClicked && enableDownload)
toggleDownloadButton();
}
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.setTitle(mContext.getString(R.string.download_multiple));
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.download_multiple, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_select_all:
if (isAllSelected) {
unselectAll();
} else
selectAll();
break;
case R.id.action_download:
downloadSelectedPatients();
finish(mode);
break;
case R.id.close_context_menu:
unselectAll();
finish(mode);
break;
default:
unselectAll();
break;
}
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
unselectAll();
isLongClicked = false;
}
public void finish(ActionMode mode){
mode.finish();
isLongClicked = false;
}
};
public void startActionMode() {
actionMode = mContext.startActionMode(mActionModeCallback);
isLongClicked = true;
}
public void finishActionMode(){
if (actionMode != null) {
actionMode.finish();
isLongClicked = false;
}
}
public void selectAll() {
for(int i = 0; i < patients.size(); i++){
selectedPatientPositions.add(i);
}
isAllSelected = true;
notifyDataSetChanged();
}
public void unselectAll() {
selectedPatientPositions.clear();
isAllSelected = false;
notifyDataSetChanged();
}
public void downloadSelectedPatients() {
ToastUtil.showShortToast(mContext, ToastUtil.ToastType.NOTICE, R.string.download_started);
for (Integer selectedPatientPosition : selectedPatientPositions) {
downloadPatient(patients.get(selectedPatientPosition), false);
}
notifyDataSetChanged();
}
public void setUpCheckBoxLogic(final PatientViewHolder holder, final Patient patient) {
if (isLongClicked) {
holder.mAvailableOfflineCheckbox.setVisibility(View.INVISIBLE);
} else {
holder.mAvailableOfflineCheckbox.setChecked(false);
holder.mAvailableOfflineCheckbox.setVisibility(View.VISIBLE);
holder.mAvailableOfflineCheckbox.setButtonDrawable(R.drawable.ic_download);
holder.mAvailableOfflineCheckbox.setText(mContext.getString(R.string.find_patients_row_checkbox_download_label));
holder.mAvailableOfflineCheckbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isLongClicked && ((CheckBox) v).isChecked()) {
downloadPatient(patient, true);
disableCheckBox(holder);
}
}
});
}
}
private void downloadPatient(final Patient patient, final Boolean showSnackBar) {
new PatientApi().downloadPatientByUuid(patient.getUuid(), new DownloadPatientCallbackListener() {
@Override
public void onPatientDownloaded(Patient newPatient) {
new PatientDAO().savePatient(newPatient)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(id -> {
new VisitApi().syncVisitsData(newPatient);
new VisitApi().syncLastVitals(newPatient.getUuid());
patients.remove(patient);
notifyDataSetChanged();
if (showSnackBar) {
view.showOpenPatientSnackbar(newPatient.getId());
}
});
}
@Override
public void onPatientPhotoDownloaded(Patient patient) {
new PatientDAO().updatePatient(patient.getId(), patient);
}
@Override
public void onResponse() {
// This method is intentionally empty
}
@Override
public void onErrorResponse(String errorMessage) {
ToastUtil.error("Failed to fetch patient data");
}
});
}
public void disableCheckBox(PatientViewHolder holder) {
holder.mAvailableOfflineCheckbox.setChecked(true);
holder.mAvailableOfflineCheckbox.setClickable(false);
holder.mAvailableOfflineCheckbox.setButtonDrawable(R.drawable.ic_offline);
}
private void toggleDownloadButton() {
if (actionMode != null) {
MenuItem item = actionMode.getMenu().findItem(R.id.action_download);
if (item.isEnabled()) {
enableDownload = false;
item.setEnabled(false);
item.getIcon().setAlpha(128);
} else {
enableDownload = true;
item.setEnabled(true);
item.getIcon().setAlpha(255);
}
}
}
}