package org.wordpress.android.ui.reader.adapters;
import android.os.AsyncTask;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.wordpress.android.R;
import org.wordpress.android.datasets.ReaderBlogTable;
import org.wordpress.android.models.ReaderBlog;
import org.wordpress.android.models.ReaderBlogList;
import org.wordpress.android.models.ReaderRecommendBlogList;
import org.wordpress.android.models.ReaderRecommendedBlog;
import org.wordpress.android.ui.reader.ReaderInterfaces;
import org.wordpress.android.util.AppLog;
import org.wordpress.android.util.AppLog.T;
import org.wordpress.android.util.StringUtils;
import org.wordpress.android.util.UrlUtils;
import org.wordpress.android.widgets.WPNetworkImageView;
import java.util.Collections;
import java.util.Comparator;
/*
* adapter which shows either recommended or followed blogs - used by ReaderBlogFragment
*/
public class ReaderBlogAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int VIEW_TYPE_ITEM = 0;
public enum ReaderBlogType {RECOMMENDED, FOLLOWED}
public interface BlogClickListener {
void onBlogClicked(Object blog);
}
private final ReaderBlogType mBlogType;
private BlogClickListener mClickListener;
private ReaderInterfaces.DataLoadedListener mDataLoadedListener;
private ReaderRecommendBlogList mRecommendedBlogs = new ReaderRecommendBlogList();
private ReaderBlogList mFollowedBlogs = new ReaderBlogList();
private String mSearchFilter;
public ReaderBlogAdapter(ReaderBlogType blogType, String searchFilter) {
super();
setHasStableIds(false);
mBlogType = blogType;
mSearchFilter = searchFilter;
}
public void setDataLoadedListener(ReaderInterfaces.DataLoadedListener listener) {
mDataLoadedListener = listener;
}
public void setBlogClickListener(BlogClickListener listener) {
mClickListener = listener;
}
public void refresh() {
if (mIsTaskRunning) {
AppLog.w(T.READER, "load blogs task is already running");
return;
}
new LoadBlogsTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private ReaderBlogType getBlogType() {
return mBlogType;
}
public boolean isEmpty() {
return (getItemCount() == 0);
}
@Override
public int getItemCount() {
switch (getBlogType()) {
case RECOMMENDED:
return mRecommendedBlogs.size();
case FOLLOWED:
return mFollowedBlogs.size();
default:
return 0;
}
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return VIEW_TYPE_ITEM;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case VIEW_TYPE_ITEM:
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.reader_listitem_blog, parent, false);
return new BlogViewHolder(itemView);
default:
return null;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof BlogViewHolder) {
final BlogViewHolder blogHolder = (BlogViewHolder) holder;
switch (getBlogType()) {
case RECOMMENDED:
final ReaderRecommendedBlog blog = mRecommendedBlogs.get(position);
blogHolder.txtTitle.setText(blog.getTitle());
blogHolder.txtDescription.setText(blog.getReason());
blogHolder.txtUrl.setText(UrlUtils.getHost(blog.getBlogUrl()));
blogHolder.imgBlog.setImageUrl(blog.getImageUrl(), WPNetworkImageView.ImageType.BLAVATAR);
break;
case FOLLOWED:
final ReaderBlog blogInfo = mFollowedBlogs.get(position);
if (blogInfo.hasName()) {
blogHolder.txtTitle.setText(blogInfo.getName());
} else {
blogHolder.txtTitle.setText(R.string.reader_untitled_post);
}
if (blogInfo.hasUrl()) {
blogHolder.txtUrl.setText(UrlUtils.getHost(blogInfo.getUrl()));
} else if (blogInfo.hasFeedUrl()) {
blogHolder.txtUrl.setText(UrlUtils.getHost(blogInfo.getFeedUrl()));
} else {
blogHolder.txtUrl.setText("");
}
blogHolder.imgBlog.setImageUrl(blogInfo.getImageUrl(), WPNetworkImageView.ImageType.BLAVATAR);
break;
}
if (mClickListener != null) {
blogHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int clickedPosition = blogHolder.getAdapterPosition();
switch (getBlogType()) {
case RECOMMENDED:
mClickListener.onBlogClicked(mRecommendedBlogs.get(clickedPosition));
break;
case FOLLOWED:
mClickListener.onBlogClicked(mFollowedBlogs.get(clickedPosition));
break;
}
}
});
}
}
}
/*
* holder used for followed/recommended blogs
*/
class BlogViewHolder extends RecyclerView.ViewHolder {
private final TextView txtTitle;
private final TextView txtDescription;
private final TextView txtUrl;
private final WPNetworkImageView imgBlog;
public BlogViewHolder(View view) {
super(view);
txtTitle = (TextView) view.findViewById(R.id.text_title);
txtDescription = (TextView) view.findViewById(R.id.text_description);
txtUrl = (TextView) view.findViewById(R.id.text_url);
imgBlog = (WPNetworkImageView) view.findViewById(R.id.image_blog);
// followed blogs don't have a description
switch (getBlogType()) {
case FOLLOWED:
txtDescription.setVisibility(View.GONE);
break;
case RECOMMENDED:
txtDescription.setVisibility(View.VISIBLE);
break;
}
}
}
private boolean mIsTaskRunning = false;
private class LoadBlogsTask extends AsyncTask<Void, Void, Boolean> {
ReaderRecommendBlogList tmpRecommendedBlogs;
ReaderBlogList tmpFollowedBlogs;
@Override
protected void onPreExecute() {
mIsTaskRunning = true;
}
@Override
protected void onCancelled() {
mIsTaskRunning = false;
}
@Override
protected Boolean doInBackground(Void... params) {
switch (getBlogType()) {
case RECOMMENDED:
tmpRecommendedBlogs = ReaderBlogTable.getRecommendedBlogs();
return !mRecommendedBlogs.isSameList(tmpRecommendedBlogs);
case FOLLOWED:
tmpFollowedBlogs = new ReaderBlogList();
ReaderBlogList allFollowedBlogs = ReaderBlogTable.getFollowedBlogs();
if (hasSearchFilter()) {
String query = mSearchFilter.toLowerCase();
for (ReaderBlog blog: allFollowedBlogs) {
if (blog.getName().toLowerCase().contains(query)) {
tmpFollowedBlogs.add(blog);
} else if (UrlUtils.getHost(blog.getUrl()).toLowerCase().contains(query)) {
tmpFollowedBlogs.add(blog);
}
}
} else {
tmpFollowedBlogs.addAll(allFollowedBlogs);
}
// sort followed blogs by name/domain to match display
Collections.sort(tmpFollowedBlogs, new Comparator<ReaderBlog>() {
@Override
public int compare(ReaderBlog thisBlog, ReaderBlog thatBlog) {
String thisName = getBlogNameForComparison(thisBlog);
String thatName = getBlogNameForComparison(thatBlog);
return thisName.compareToIgnoreCase(thatName);
}
});
return !mFollowedBlogs.isSameList(tmpFollowedBlogs);
default:
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
switch (getBlogType()) {
case RECOMMENDED:
mRecommendedBlogs = (ReaderRecommendBlogList) tmpRecommendedBlogs.clone();
break;
case FOLLOWED:
mFollowedBlogs = (ReaderBlogList) tmpFollowedBlogs.clone();
break;
}
notifyDataSetChanged();
}
mIsTaskRunning = false;
if (mDataLoadedListener != null) {
mDataLoadedListener.onDataLoaded(isEmpty());
}
}
private String getBlogNameForComparison(ReaderBlog blog) {
if (blog == null) {
return "";
} else if (blog.hasName()) {
return blog.getName();
} else if (blog.hasUrl()) {
return StringUtils.notNullStr(UrlUtils.getHost(blog.getUrl()));
} else {
return "";
}
}
}
public String getSearchFilter() {
return mSearchFilter;
}
/*
* filters the list of followed sites - pass null to show all
*/
public void setSearchFilter(String constraint) {
if (!StringUtils.equals(constraint, mSearchFilter)) {
mSearchFilter = constraint;
refresh();
}
}
public boolean hasSearchFilter() {
return !TextUtils.isEmpty(mSearchFilter);
}
}