package info.guardianproject.securereaderinterface.adapters;
import info.guardianproject.securereaderinterface.App;
import info.guardianproject.securereaderinterface.models.FeedFilterType;
import info.guardianproject.securereaderinterface.ui.MediaViewCollection;
import info.guardianproject.securereaderinterface.ui.UICallbacks;
import info.guardianproject.securereaderinterface.ui.MediaViewCollection.OnMediaLoadedListener;
import info.guardianproject.securereaderinterface.views.StoryItemPageView;
import info.guardianproject.securereaderinterface.views.StoryItemPageView.StoryItemPageViewListener;
import info.guardianproject.securereaderinterface.views.StoryItemPageView.ViewType;
import info.guardianproject.securereaderinterface.views.StoryListView.StoryListListener;
import java.util.ArrayList;
import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.tinymission.rss.Item;
import com.tinymission.rss.MediaContent;
public class StoryListAdapter extends BaseAdapter implements OnMediaLoadedListener, Filterable, StoryItemPageViewListener
{
public interface OnTagClickedListener
{
void onTagClicked(String tag);
}
public interface OnHeaderCreatedListener
{
void onHeaderCreated(View headerView, int resIdHeader);
}
protected final Context mContext;
protected final LayoutInflater mInflater;
private ArrayList<Item> mStories;
private ArrayList<Item> mFilteredStories;
private boolean mShowTags;
protected OnTagClickedListener mOnTagClickedListener;
protected OnHeaderCreatedListener mOnHeaderCreatedListener;
private StoryListListener mListener;
private int mResIdHeaderView;
private boolean mHeaderOnlyIfNoItems;
private String mTagFilter;
private boolean mDeferMediaLoading;
private Filter mFilter;
public StoryListAdapter(Context context, ArrayList<Item> stories)
{
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mStories = mFilteredStories = stories;
mShowTags = false;
mOnTagClickedListener = null;
mHeaderOnlyIfNoItems = false;
}
public void setHeaderView(int resIdHeaderView, boolean onlyIfNoItems)
{
if (resIdHeaderView != mResIdHeaderView)
{
mResIdHeaderView = resIdHeaderView;
mHeaderOnlyIfNoItems = onlyIfNoItems;
}
}
public void updateItems(ArrayList<Item> items)
{
mStories = items;
applyFilters(); // Will call NotifyDataSetChanged when complete
}
public void setTagFilter(String tagFilter)
{
if (!TextUtils.equals(mTagFilter, tagFilter))
{
mTagFilter = tagFilter;
applyFilters();
}
}
private void applyFilters()
{
getFilter().filter(mTagFilter);
}
public void setListener(StoryListListener listener)
{
mListener = listener;
}
public boolean showTags()
{
return mShowTags;
}
public void setShowTags(boolean showTags)
{
mShowTags = showTags;
}
public void setOnTagClickedListener(OnTagClickedListener listener)
{
mOnTagClickedListener = listener;
}
public void setOnHeaderCreatedListener(OnHeaderCreatedListener listener)
{
mOnHeaderCreatedListener = listener;
}
@Override
public boolean hasStableIds()
{
return true;
}
private boolean hasHeaderView()
{
return (mResIdHeaderView != 0) && (!mHeaderOnlyIfNoItems || mFilteredStories == null || mFilteredStories.size() == 0);
}
@Override
public int getItemViewType(int position)
{
if (position == 0 && hasHeaderView())
return 0; // This is a header type
Item item = (Item) getItem(position);
int type = 1; // No media
ArrayList<MediaContent> media = item.getMediaContent();
if (media != null && media.size() > 0)
{
if (Iterables.any(media, new Predicate<MediaContent>()
{
@Override
public boolean apply(MediaContent mc)
{
return App.getInstance().socialReader.isMediaContentLoaded(mc);
}
}))
{
if (media.get(0).getHeight() > media.get(0).getWidth())
type = 2;
else
type = 3;
}
}
return type;
}
@Override
public int getViewTypeCount()
{
// We have an (optional) header and three types of items
return 4;
}
@Override
public int getCount()
{
int count = 0;
if (mFilteredStories != null)
count = mFilteredStories.size();
if (hasHeaderView())
count += 1;
return count;
}
@Override
public Object getItem(int position)
{
if (position == 0 && hasHeaderView())
return mResIdHeaderView;
if (mFilteredStories == null || mFilteredStories.size() == 0)
return null;
return mFilteredStories.get(position - (hasHeaderView() ? 1 : 0));
}
@Override
public long getItemId(int position)
{
if (position == 0 && hasHeaderView())
return -1;
if (mFilteredStories == null || mFilteredStories.size() == 0)
return -1;
return mFilteredStories.get(position - (hasHeaderView() ? 1 : 0)).getDatabaseId();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent)
{
if (position == 0 && hasHeaderView())
{
View headerView = convertView;
if (headerView == null || headerView.getTag() == null || Integer.valueOf(mResIdHeaderView).compareTo((Integer) headerView.getTag()) != 0)
{
headerView = mInflater.inflate(mResIdHeaderView, parent, false);
headerView.setTag(Integer.valueOf(mResIdHeaderView));
}
if (this.mOnHeaderCreatedListener != null)
this.mOnHeaderCreatedListener.onHeaderCreated(headerView, mResIdHeaderView);
return headerView;
}
View view = (convertView != null) ? convertView : createView(position, parent);
bindView(view, position, (Item) getItem(position));
return view;
}
protected View createView(int position, ViewGroup parent)
{
int type = getItemViewType(position);
StoryItemPageView view = new StoryItemPageView(parent.getContext());
if (type == 1)
view.createViews(ViewType.NO_PHOTO);
else if (type == 2)
view.createViews(ViewType.PORTRAIT_PHOTO);
else
view.createViews(ViewType.LANDSCAPE_PHOTO);
return view;
}
protected void bindView(View view, int position, Item item)
{
StoryItemPageView pv = (StoryItemPageView) view;
pv.showTags(mShowTags);
pv.setListener(this);
pv.populateWithItem(item);
if (!getDeferMediaLoading())
pv.loadMedia(this);
view.setOnClickListener(new ItemClickListener(position));
}
// public void recycleView(View view)
// {
// if (view != null && view instanceof StoryItemPageView)
// ((StoryItemPageView) view).recycle();
// }
public void setDeferMediaLoading(boolean deferMediaLoading)
{
if (mDeferMediaLoading != deferMediaLoading)
{
mDeferMediaLoading = deferMediaLoading;
}
}
public boolean getDeferMediaLoading()
{
return mDeferMediaLoading;
}
protected class ItemClickListener implements View.OnClickListener
{
private final int mPosition;
public ItemClickListener(int position)
{
mPosition = position;
}
@Override
public void onClick(View v)
{
int positionInList = mPosition - (hasHeaderView() ? 1 : 0);
if (mListener != null)
mListener.onStoryClicked(mFilteredStories, positionInList, v);
}
}
@Override
public void onViewLoaded(MediaViewCollection collection, int index, boolean wasCached)
{
// If it was not cached it means we need to reload cause the layout has changed
if (!wasCached)
notifyDataSetChanged();
}
@Override
public Filter getFilter()
{
if (mFilter == null)
{
mFilter = new Filter()
{
@Override
protected FilterResults performFiltering(CharSequence constraint)
{
ArrayList<Item> filteredStories = null;
if (mStories != null)
{
filteredStories = new ArrayList<Item>();
for (Item item : mStories)
{
if (constraint != null)
{
if (item.getTags() != null)
{
boolean bFoundTag = false;
for (String tag : item.getTags())
{
if (tag.contains(constraint))
{
bFoundTag = true;
break;
}
}
if (!bFoundTag)
continue; // Don't add this, i.e. filter
// it
}
}
filteredStories.add(item);
}
}
FilterResults results = new FilterResults();
results.count = (filteredStories != null) ? filteredStories.size() : 0;
results.values = filteredStories;
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
{
if (TextUtils.isEmpty(constraint))
mFilteredStories = mStories;
else if (results.count > 0)
mFilteredStories = (ArrayList<Item>) results.values;
else
mFilteredStories = null;
notifyDataSetChanged();
}
};
}
return mFilter;
}
@Override
public void onSourceClicked(long feedId)
{
UICallbacks.setFeedFilter(FeedFilterType.SINGLE_FEED, feedId, this);
}
@Override
public void onTagClicked(String tag)
{
if (mOnTagClickedListener != null)
mOnTagClickedListener.onTagClicked(tag);
}
}