/*
* Copyright (c) 2014. The Trustees of Indiana University.
*
* This version of the code is licensed under the MPL 2.0 Open Source license with additional
* healthcare disclaimer. If the user is an entity intending to commercialize any application
* that uses this code in a for-profit venture, please contact the copyright holder.
*/
package com.muzima.adapters.concept;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Filter;
import android.widget.TextView;
import android.widget.Toast;
import com.muzima.MuzimaApplication;
import com.muzima.R;
import com.muzima.domain.Credentials;
import com.muzima.service.MuzimaSyncService;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import static com.muzima.utils.Constants.DataSyncServiceConstants.SyncStatusConstants;
/**
* Responsible to display auto-complete menu for Concept and Cohort.
* @param <T> T can be of Type Concept or Cohort. Objects displayed in the auto-complete menu.
*/
public abstract class AutoCompleteBaseAdapter<T> extends ArrayAdapter<T> {
private static final String TAG = AutoCompleteBaseAdapter.class.getSimpleName();
protected WeakReference<MuzimaApplication> muzimaApplicationWeakReference;
private final MuzimaSyncService muzimaSyncService;
private String previousConstraint = null;
private List<T> previousResult = null;
private AutoCompleteTextView autoCompleteTextView;
public AutoCompleteBaseAdapter(Context context, int textViewResourceId, AutoCompleteTextView autoCompleteTextView) {
super(context, textViewResourceId);
this.autoCompleteTextView = autoCompleteTextView;
muzimaApplicationWeakReference = new WeakReference<MuzimaApplication>((MuzimaApplication) context);
muzimaSyncService = getMuzimaApplicationContext().getMuzimaSyncService();
}
public MuzimaApplication getMuzimaApplicationContext() {
if (muzimaApplicationWeakReference == null) {
return null;
} else {
return muzimaApplicationWeakReference.get();
}
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(final CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null && constraint.length() > 2) {
List<T> options;
if (hasResultStored(constraint)) {
options = filterOptionsLocally(constraint);
} else {
options = downloadOptions(constraint);
}
filterResults.values = options;
filterResults.count = options.size();
}
return filterResults;
}
private List<T> downloadOptions(CharSequence constraint) {
List<T> options = new ArrayList<T>();
Credentials credentials = new Credentials(getContext());
MuzimaApplication muzimaApplicationContext = getMuzimaApplicationContext();
try {
if (muzimaSyncService.authenticate(credentials.getCredentialsArray(),false) == SyncStatusConstants.AUTHENTICATION_SUCCESS) {
options = getOptions(constraint);
previousConstraint = constraint.toString();
previousResult = options;
} else {
Toast.makeText(getMuzimaApplicationContext(), muzimaApplicationContext.getString(R.string.error_authentication_fail), Toast.LENGTH_SHORT).show();
}
Log.i(TAG, "Downloaded: " + options.size());
} catch (Throwable t) {
Log.e(TAG, "Unable to download options!", t);
} finally {
muzimaApplicationContext.getMuzimaContext().closeSession();
}
return options;
}
protected List<T> filterOptionsLocally(CharSequence constraint) {
List<T> result = new ArrayList<T>();
for (T t : previousResult) {
if (getOptionName(t).toLowerCase().startsWith(constraint.toString().toLowerCase())) {
result.add(t);
}
}
return result;
}
private boolean hasResultStored(CharSequence constraint) {
return previousConstraint != null &&
previousResult != null &&
constraint.toString().toLowerCase().startsWith(previousConstraint.toLowerCase());
}
@Override
protected void publishResults(final CharSequence constraint, final FilterResults results) {
if (constraint != null && constraint.toString().equals(autoCompleteTextView.getText().toString())) {
List<T> optionList = (List<T>) results.values;
if (optionList != null && optionList.size() > 0) {
clear();
for (T c : optionList) {
add(c);
}
notifyDataSetChanged();
}
}else{
clear();
}
}
};
}
protected abstract List<T> getOptions(CharSequence constraint);
private class ViewHolder {
TextView name;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
convertView = layoutInflater.inflate(R.layout.item_option_autocomplete, parent, false);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.option_autocomplete_name);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
T option = getItem(position);
holder.name.setText(getOptionName(option));
return convertView;
}
protected abstract String getOptionName(T option);
}