app/src/main/java/ch/epfl/sweng/favors/favors/FavorListAdapter.java
package ch.epfl.sweng.favors.favors;
import android.arch.lifecycle.ViewModelProviders;
import android.databinding.ObservableField;
import android.net.Uri;
import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Filter;
import android.widget.Filterable;
import com.google.firebase.Timestamp;
import com.google.firebase.firestore.GeoPoint;
import java.util.Date;
import ch.epfl.sweng.favors.R;
import ch.epfl.sweng.favors.authentication.Authentication;
import ch.epfl.sweng.favors.database.Favor;
import ch.epfl.sweng.favors.database.ObservableArrayList;
import ch.epfl.sweng.favors.location.LocationHandler;
import ch.epfl.sweng.favors.utils.Utils;
import static ch.epfl.sweng.favors.utils.Utils.getIconPathFromCategory;
/**
* FavorListAdapter
* Class that represents the graphical list view to display Favors
* sets the fields that shpould be visible in the ListView
* favor_item.xml (item of list) and fragment_favors.xml (list)
*/
public class FavorListAdapter extends RecyclerView.Adapter<FavorListAdapter.FavorViewHolder> implements Filterable {
private ObservableArrayList<Favor> favorList;
private ObservableArrayList<Favor> filteredFavorList;
private SharedViewFavor sharedViewFavor;
private FragmentActivity fragmentActivity;
private OnItemClickListener listener;
private static final String TAG = "FAVOR_ADAPTER_LIST";
public interface OnItemClickListener {
void onItemClick(Favor item);
}
/**
* Class that represents a single row in the list of Favor
*/
public class FavorViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView title, timestamp, location, distance, category;
public ImageView iconCategory;
public FavorListAdapter adapter;
// FIXME ObservableFields
public FavorViewHolder(View itemView, FavorListAdapter adapter) {
super(itemView);
//initialize TextViews
title = itemView.findViewById(R.id.title);
timestamp = itemView.findViewById(R.id.timestamp);
location = itemView.findViewById(R.id.location);
distance = itemView.findViewById(R.id.distance);
category = itemView.findViewById(R.id.category);
iconCategory = itemView.findViewById(R.id.iconCategory);
this.adapter = adapter;
}
@Override
public void onClick(View v) {}
public void bind(final Favor item, final OnItemClickListener listener){
setStringFields(item);
setTimestamp(item);
setLocation(item);
setIconCategory(item);
itemView.setOnClickListener(v -> listener.onItemClick(item));
}
/**
* sets the location city and
* the current distance to a favor
* @param favor
*/
private void setLocation(Favor favor) {
if(favor.get(Favor.StringFields.locationCity) != null)
location.setText(favor.get(Favor.StringFields.locationCity));
if(favor.get(Favor.ObjectFields.location) != null) {
ObservableField<Object> geo = favor.getObservableObject(Favor.ObjectFields.location);
// distanceBetween two
distance.setText(LocationHandler.distanceBetween((GeoPoint)geo.get()));
} else { distance.setText("--"); }
}
/**
* Sets all the StringFields of a Favor
* currently:
* Title
* Description
* Category
* @param favor the relevant favor
*/
private void setStringFields(Favor favor) {
String titleStr = favor.get(Favor.StringFields.title);
if(titleStr != null){
if(titleStr.length() > 23){
titleStr = titleStr.subSequence(0, 22).toString();
titleStr = titleStr.concat("...");
}
title.setText(titleStr);
}
if(favor.get(Favor.StringFields.category) != null)
category.setText(favor.get(Favor.StringFields.category));
}
/**
* sets the timestamp fetched from the db
* @param favor
*/
private void setTimestamp(Favor favor) {
if(favor.get(Favor.ObjectFields.expirationTimestamp) != null) {
Date d;
if(favor.get(Favor.ObjectFields.expirationTimestamp) instanceof Timestamp)
d = ((Timestamp)favor.get(Favor.ObjectFields.expirationTimestamp)).toDate();
else d = (Date) favor.get(Favor.ObjectFields.expirationTimestamp);
timestamp.setText(Utils.getFavorDate(d));
} else { timestamp.setText("--"); }
}
/**
* sets the icon category
* @param favor
*/
private void setIconCategory(Favor favor){
if(favor.get(Favor.StringFields.category) != null){
iconCategory.setImageURI(Uri.parse(getIconPathFromCategory(favor.get(Favor.StringFields.category))));
}
}
}
/**
* Constructor for a FavorListAdapter
* @param fragActivity
* @param favorList
*/
public FavorListAdapter(FragmentActivity fragActivity, ObservableArrayList<Favor> favorList) {
this.favorList = favorList;
this.filteredFavorList = favorList;
if(fragActivity != null) this.sharedViewFavor = ViewModelProviders.of(fragActivity).get(SharedViewFavor.class);
this.fragmentActivity = fragActivity;
this.listener = (Favor item) -> {
Log.d(TAG,"click recorded");
this.sharedViewFavor.select(item);
if(item.get(Favor.StringFields.ownerID).equals(Authentication.getInstance().getUid()))
fragmentActivity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new FavorDetailView()).addToBackStack(null).commit();
else
fragmentActivity.getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, new FavorDetailView()).addToBackStack(null).commit();
};
}
@Override
public FavorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//set layout to itemView using Layout inflater
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.favor_item, parent, false);
return new FavorViewHolder(itemView, this);
}
@Override
public void onBindViewHolder(FavorViewHolder holder, int position) {
holder.bind(filteredFavorList.get(position), listener);
}
@Override
public int getItemCount() {
return filteredFavorList.size();
}
/**
* @param f favor
* @param s string input
* @return whether s matches favor's title, description, category or location city
*/
private Boolean checkSearch(Favor f, String s){
String slc = s.toLowerCase();
return f.get(Favor.StringFields.title).toLowerCase().contains(slc) ||
f.get(Favor.StringFields.description).toLowerCase().contains(slc) ||
f.get(Favor.StringFields.category).toLowerCase().contains(slc) ||
f.get(Favor.StringFields.locationCity).toLowerCase().contains(slc);
}
protected Filter searchFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
String searchInput = constraint.toString();
if (searchInput.isEmpty()) {
filteredFavorList = favorList;
} else {
ObservableArrayList<Favor> filteredList = new ObservableArrayList<>();
for (Favor f : favorList) {
if (checkSearch(f, searchInput)) {
filteredList.add(f);
}
}
filteredFavorList = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = filteredFavorList;
return filterResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredFavorList = (ObservableArrayList<Favor>) results.values;
notifyDataSetChanged();
}
};
@Override
public Filter getFilter() {
return searchFilter;
}
}