package org.wordpress.android.ui.reader;

import android.app.Fragment;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.ListPopupWindow;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.text.Html;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import org.wordpress.android.R;
import org.wordpress.android.analytics.AnalyticsTracker;
import org.wordpress.android.datasets.ReaderBlogTable;
import org.wordpress.android.datasets.ReaderDatabase;
import org.wordpress.android.datasets.ReaderPostTable;
import org.wordpress.android.datasets.ReaderSearchTable;
import org.wordpress.android.datasets.ReaderTagTable;
import org.wordpress.android.models.FilterCriteria;
import org.wordpress.android.models.ReaderPost;
import org.wordpress.android.models.ReaderPostDiscoverData;
import org.wordpress.android.models.ReaderTag;
import org.wordpress.android.models.ReaderTagList;
import org.wordpress.android.models.ReaderTagType;
import org.wordpress.android.ui.EmptyViewMessageType;
import org.wordpress.android.ui.FilteredRecyclerView;
import org.wordpress.android.ui.main.WPMainActivity;
import org.wordpress.android.ui.prefs.AppPrefs;
import org.wordpress.android.ui.reader.ReaderTypes.ReaderPostListType;
import org.wordpress.android.ui.reader.actions.ReaderActions;
import org.wordpress.android.ui.reader.actions.ReaderBlogActions;
import org.wordpress.android.ui.reader.actions.ReaderBlogActions.BlockedBlogResult;
import org.wordpress.android.ui.reader.adapters.ReaderMenuAdapter;
import org.wordpress.android.ui.reader.adapters.ReaderPostAdapter;
import org.wordpress.android.ui.reader.adapters.ReaderSearchSuggestionAdapter;
import org.wordpress.android.ui.reader.services.ReaderPostService;
import org.wordpress.android.ui.reader.services.ReaderPostService.UpdateAction;
import org.wordpress.android.ui.reader.services.ReaderSearchService;
import org.wordpress.android.ui.reader.services.ReaderUpdateService;
import org.wordpress.android.ui.reader.services.ReaderUpdateService.UpdateTask;
import org.wordpress.android.ui.reader.utils.ReaderUtils;
import org.wordpress.android.ui.reader.views.ReaderSiteHeaderView;
import org.wordpress.android.util.AnalyticsUtils;
import org.wordpress.android.util.AniUtils;
import org.wordpress.android.util.AppLog;
import org.wordpress.android.util.AppLog.T;
import org.wordpress.android.util.DateTimeUtils;
import org.wordpress.android.util.DisplayUtils;
import org.wordpress.android.util.NetworkUtils;
import org.wordpress.android.util.ToastUtils;
import org.wordpress.android.util.WPActivityUtils;
import org.wordpress.android.widgets.RecyclerItemDecoration;

import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import de.greenrobot.event.EventBus;

public class ReaderPostListFragment extends Fragment
        implements ReaderInterfaces.OnPostSelectedListener,
                   ReaderInterfaces.OnTagSelectedListener,
                   ReaderInterfaces.OnPostPopupListener,
                   WPMainActivity.OnActivityBackPressedListener,
                   WPMainActivity.OnScrollToTopListener {

    private ReaderPostAdapter mPostAdapter;
    private ReaderSearchSuggestionAdapter mSearchSuggestionAdapter;

    private FilteredRecyclerView mRecyclerView;
    private boolean mFirstLoad = true;
    private final ReaderTagList mTags = new ReaderTagList();

    private View mNewPostsBar;
    private View mEmptyView;
    private View mEmptyViewBoxImages;
    private ProgressBar mProgress;

    private SearchView mSearchView;
    private MenuItem mSettingsMenuItem;
    private MenuItem mSearchMenuItem;

    private ReaderTag mCurrentTag;
    private long mCurrentBlogId;
    private long mCurrentFeedId;
    private String mCurrentSearchQuery;
    private ReaderPostListType mPostListType;

    private int mRestorePosition;

    private boolean mIsUpdating;
    private boolean mWasPaused;
    private boolean mHasUpdatedPosts;
    private boolean mIsAnimatingOutNewPostsBar;

    private static boolean mHasPurgedReaderDb;
    private static Date mLastAutoUpdateDt;

    private final HistoryStack mTagPreviewHistory = new HistoryStack("tag_preview_history");

    private static class HistoryStack extends Stack<String> {
        private final String keyName;
        HistoryStack(@SuppressWarnings("SameParameterValue") String keyName) {
            this.keyName = keyName;
        }
        void restoreInstance(Bundle bundle) {
            clear();
            if (bundle.containsKey(keyName)) {
                ArrayList<String> history = bundle.getStringArrayList(keyName);
                if (history != null) {
                    this.addAll(history);
                }
            }
        }
        void saveInstance(Bundle bundle) {
            if (!isEmpty()) {
                ArrayList<String> history = new ArrayList<>();
                history.addAll(this);
                bundle.putStringArrayList(keyName, history);
            }
        }
    }

    public static ReaderPostListFragment newInstance() {
        ReaderTag tag = AppPrefs.getReaderTag();
        if (tag == null) {
            tag = ReaderUtils.getDefaultTag();
        }
        return newInstanceForTag(tag, ReaderPostListType.TAG_FOLLOWED);
    }

    /*
     * show posts with a specific tag (either TAG_FOLLOWED or TAG_PREVIEW)
     */
    static ReaderPostListFragment newInstanceForTag(ReaderTag tag, ReaderPostListType listType) {
        AppLog.d(T.READER, "reader post list > newInstance (tag)");

        Bundle args = new Bundle();
        args.putSerializable(ReaderConstants.ARG_TAG, tag);
        args.putSerializable(ReaderConstants.ARG_POST_LIST_TYPE, listType);

        ReaderPostListFragment fragment = new ReaderPostListFragment();
        fragment.setArguments(args);

        return fragment;
    }

    /*
     * show posts in a specific blog
     */
    public static ReaderPostListFragment newInstanceForBlog(long blogId) {
        AppLog.d(T.READER, "reader post list > newInstance (blog)");

        Bundle args = new Bundle();
        args.putLong(ReaderConstants.ARG_BLOG_ID, blogId);
        args.putSerializable(ReaderConstants.ARG_POST_LIST_TYPE, ReaderPostListType.BLOG_PREVIEW);

        ReaderPostListFragment fragment = new ReaderPostListFragment();
        fragment.setArguments(args);

        return fragment;
    }

    public static ReaderPostListFragment newInstanceForFeed(long feedId) {
        AppLog.d(T.READER, "reader post list > newInstance (blog)");

        Bundle args = new Bundle();
        args.putLong(ReaderConstants.ARG_FEED_ID, feedId);
        args.putLong(ReaderConstants.ARG_BLOG_ID, feedId);
        args.putSerializable(ReaderConstants.ARG_POST_LIST_TYPE, ReaderPostListType.BLOG_PREVIEW);

        ReaderPostListFragment fragment = new ReaderPostListFragment();
        fragment.setArguments(args);

        return fragment;
    }

    @Override
    public void setArguments(Bundle args) {
        super.setArguments(args);

        if (args != null) {
            if (args.containsKey(ReaderConstants.ARG_TAG)) {
                mCurrentTag = (ReaderTag) args.getSerializable(ReaderConstants.ARG_TAG);
            }
            if (args.containsKey(ReaderConstants.ARG_POST_LIST_TYPE)) {
                mPostListType = (ReaderPostListType) args.getSerializable(ReaderConstants.ARG_POST_LIST_TYPE);
            }

            mCurrentBlogId = args.getLong(ReaderConstants.ARG_BLOG_ID);
            mCurrentFeedId = args.getLong(ReaderConstants.ARG_FEED_ID);
            mCurrentSearchQuery = args.getString(ReaderConstants.ARG_SEARCH_QUERY);

            if (getPostListType() == ReaderPostListType.TAG_PREVIEW && hasCurrentTag()) {
                mTagPreviewHistory.push(getCurrentTagName());
            }
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState != null) {
            AppLog.d(T.READER, "reader post list > restoring instance state");
            if (savedInstanceState.containsKey(ReaderConstants.ARG_TAG)) {
                mCurrentTag = (ReaderTag) savedInstanceState.getSerializable(ReaderConstants.ARG_TAG);
            }
            if (savedInstanceState.containsKey(ReaderConstants.ARG_BLOG_ID)) {
                mCurrentBlogId = savedInstanceState.getLong(ReaderConstants.ARG_BLOG_ID);
            }
            if (savedInstanceState.containsKey(ReaderConstants.ARG_FEED_ID)) {
                mCurrentFeedId = savedInstanceState.getLong(ReaderConstants.ARG_FEED_ID);
            }
            if (savedInstanceState.containsKey(ReaderConstants.ARG_SEARCH_QUERY)) {
                mCurrentSearchQuery = savedInstanceState.getString(ReaderConstants.ARG_SEARCH_QUERY);
            }
            if (savedInstanceState.containsKey(ReaderConstants.ARG_POST_LIST_TYPE)) {
                mPostListType = (ReaderPostListType) savedInstanceState.getSerializable(ReaderConstants.ARG_POST_LIST_TYPE);
            }
            if (getPostListType() == ReaderPostListType.TAG_PREVIEW) {
                mTagPreviewHistory.restoreInstance(savedInstanceState);
            }
            mRestorePosition = savedInstanceState.getInt(ReaderConstants.KEY_RESTORE_POSITION);
            mWasPaused = savedInstanceState.getBoolean(ReaderConstants.KEY_WAS_PAUSED);
            mHasUpdatedPosts = savedInstanceState.getBoolean(ReaderConstants.KEY_ALREADY_UPDATED);
            mFirstLoad = savedInstanceState.getBoolean(ReaderConstants.KEY_FIRST_LOAD);
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        mWasPaused = true;
    }

    @Override
    public void onResume() {
        super.onResume();
        checkPostAdapter();

        if (mWasPaused) {
            AppLog.d(T.READER, "reader post list > resumed from paused state");
            mWasPaused = false;
            if (getPostListType() == ReaderPostListType.TAG_FOLLOWED) {
                resumeFollowedTag();
            } else {
                refreshPosts();
            }

            // if the user was searching, make sure the filter toolbar is showing
            // so the user can see the search keyword they entered
            if (getPostListType() == ReaderPostListType.SEARCH_RESULTS) {
                mRecyclerView.showToolbar();
            }
        }
    }

    /*
     * called when fragment is resumed and we're looking at posts in a followed tag
     */
    private void resumeFollowedTag() {
        Object event = EventBus.getDefault().getStickyEvent(ReaderEvents.TagAdded.class);
        if (event != null) {
            // user just added a tag so switch to it.
            String tagName = ((ReaderEvents.TagAdded) event).getTagName();
            EventBus.getDefault().removeStickyEvent(event);
            ReaderTag newTag = ReaderUtils.getTagFromTagName(tagName, ReaderTagType.FOLLOWED);
            setCurrentTag(newTag);
        } else if (!ReaderTagTable.tagExists(getCurrentTag())) {
            // current tag no longer exists, revert to default
            AppLog.d(T.READER, "reader post list > current tag no longer valid");
            setCurrentTag(ReaderUtils.getDefaultTag());
        } else {
            // otherwise, refresh posts to make sure any changes are reflected and auto-update
            // posts in the current tag if it's time
            refreshPosts();
            updateCurrentTagIfTime();
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);

        reloadTags();

        // purge database and update followed tags/blog if necessary - note that we don't purge unless
        // there's a connection to avoid removing posts the user would expect to see offline
        if (getPostListType() == ReaderPostListType.TAG_FOLLOWED && NetworkUtils.isNetworkAvailable(getActivity())) {
            purgeDatabaseIfNeeded();
            updateFollowedTagsAndBlogsIfNeeded();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }

    /*
     * ensures the adapter is created and posts are updated if they haven't already been
     */
    private void checkPostAdapter()  {
        if (isAdded() && mRecyclerView.getAdapter() == null) {
            mRecyclerView.setAdapter(getPostAdapter());

            if (!mHasUpdatedPosts && NetworkUtils.isNetworkAvailable(getActivity())) {
                mHasUpdatedPosts = true;
                if (getPostListType().isTagType()) {
                    updateCurrentTagIfTime();
                } else if (getPostListType() == ReaderPostListType.BLOG_PREVIEW) {
                    updatePostsInCurrentBlogOrFeed(UpdateAction.REQUEST_NEWER);
                }
            }
        }
    }

    /*
     * reset the post adapter to initial state and create it again using the passed list type
     */
    private void resetPostAdapter(ReaderPostListType postListType) {
        mPostListType = postListType;
        mPostAdapter = null;
        mRecyclerView.setAdapter(null);
        mRecyclerView.setAdapter(getPostAdapter());
        mRecyclerView.setSwipeToRefreshEnabled(isSwipeToRefreshSupported());
    }

    @SuppressWarnings("unused")
    public void onEventMainThread(ReaderEvents.FollowedTagsChanged event) {
        if (getPostListType() == ReaderPostListType.TAG_FOLLOWED) {
            // reload the tag filter since tags have changed
            reloadTags();

            // update the current tag if the list fragment is empty - this will happen if
            // the tag table was previously empty (ie: first run)
            if (isPostAdapterEmpty()) {
                updateCurrentTag();
            }
        }
    }

    @SuppressWarnings("unused")
    public void onEventMainThread(ReaderEvents.FollowedBlogsChanged event) {
        // refresh posts if user is viewing "Followed Sites"
        if (getPostListType() == ReaderPostListType.TAG_FOLLOWED
                && hasCurrentTag()
                && getCurrentTag().isFollowedSites()) {
            refreshPosts();
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        AppLog.d(T.READER, "reader post list > saving instance state");

        if (mCurrentTag != null) {
            outState.putSerializable(ReaderConstants.ARG_TAG, mCurrentTag);
        }
        if (getPostListType() == ReaderPostListType.TAG_PREVIEW) {
            mTagPreviewHistory.saveInstance(outState);
        }

        outState.putLong(ReaderConstants.ARG_BLOG_ID, mCurrentBlogId);
        outState.putLong(ReaderConstants.ARG_FEED_ID, mCurrentFeedId);
        outState.putString(ReaderConstants.ARG_SEARCH_QUERY, mCurrentSearchQuery);
        outState.putBoolean(ReaderConstants.KEY_WAS_PAUSED, mWasPaused);
        outState.putBoolean(ReaderConstants.KEY_ALREADY_UPDATED, mHasUpdatedPosts);
        outState.putBoolean(ReaderConstants.KEY_FIRST_LOAD, mFirstLoad);
        outState.putInt(ReaderConstants.KEY_RESTORE_POSITION, getCurrentPosition());
        outState.putSerializable(ReaderConstants.ARG_POST_LIST_TYPE, getPostListType());

        super.onSaveInstanceState(outState);
    }

    private int getCurrentPosition() {
        if (mRecyclerView != null && hasPostAdapter()) {
            return mRecyclerView.getCurrentPosition();
        } else {
            return -1;
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.reader_fragment_post_cards, container, false);
        mRecyclerView = (FilteredRecyclerView) rootView.findViewById(R.id.reader_recycler_view);

        Context context = container.getContext();

        // view that appears when current tag/blog has no posts - box images in this view are
        // displayed and animated for tags only
        mEmptyView = rootView.findViewById(R.id.empty_custom_view);
        mEmptyViewBoxImages = mEmptyView.findViewById(R.id.layout_box_images);

        mRecyclerView.setLogT(AppLog.T.READER);
        mRecyclerView.setCustomEmptyView(mEmptyView);
        mRecyclerView.setFilterListener(new FilteredRecyclerView.FilterListener() {
            @Override
            public List<FilterCriteria> onLoadFilterCriteriaOptions(boolean refresh) {
                return null;
            }

            @Override
            public void onLoadFilterCriteriaOptionsAsync(
                    FilteredRecyclerView.FilterCriteriaAsyncLoaderListener listener, boolean refresh) {

                loadTags(listener);
            }

            @Override
            public void onLoadData() {
                if (!isAdded()) {
                    return;
                }
                if (!NetworkUtils.checkConnection(getActivity())) {
                    mRecyclerView.setRefreshing(false);
                    return;
                }

                if (mFirstLoad){
                    /* let onResume() take care of this logic, as the FilteredRecyclerView.FilterListener onLoadData method
                    * is called on two moments: once for first time load, and then each time the swipe to refresh gesture
                    * triggers a refresh
                    */
                    mRecyclerView.setRefreshing(false);
                    mFirstLoad = false;
                } else {
                    switch (getPostListType()) {
                        case TAG_FOLLOWED:
                        case TAG_PREVIEW:
                            updatePostsWithTag(getCurrentTag(), UpdateAction.REQUEST_NEWER);
                            break;
                        case BLOG_PREVIEW:
                            updatePostsInCurrentBlogOrFeed(UpdateAction.REQUEST_NEWER);
                            break;
                    }
                    // make sure swipe-to-refresh progress shows since this is a manual refresh
                    mRecyclerView.setRefreshing(true);
                }
            }

            @Override
            public void onFilterSelected(int position, FilterCriteria criteria) {
                onTagChanged((ReaderTag)criteria);
            }

            @Override
            public FilterCriteria onRecallSelection() {
                if (hasCurrentTag()) {
                    return getCurrentTag();
                } else {
                    AppLog.w(T.READER, "reader post list > no current tag in onRecallSelection");
                    return ReaderUtils.getDefaultTag();
                }
            }

            @Override
            public String onShowEmptyViewMessage(EmptyViewMessageType emptyViewMsgType) {
                return null;
            }

            @Override
            public void onShowCustomEmptyView (EmptyViewMessageType emptyViewMsgType) {
                setEmptyTitleAndDescription(
                        EmptyViewMessageType.NETWORK_ERROR.equals(emptyViewMsgType)
                                || EmptyViewMessageType.PERMISSION_ERROR.equals(emptyViewMsgType)
                                || EmptyViewMessageType.GENERIC_ERROR.equals(emptyViewMsgType));
            }

        });

        // add the item decoration (dividers) to the recycler, skipping the first item if the first
        // item is the tag toolbar (shown when viewing posts in followed tags) - this is to avoid
        // having the tag toolbar take up more vertical space than necessary
        int spacingHorizontal = context.getResources().getDimensionPixelSize(R.dimen.reader_card_margin);
        int spacingVertical = context.getResources().getDimensionPixelSize(R.dimen.reader_card_gutters);
        mRecyclerView.addItemDecoration(new RecyclerItemDecoration(spacingHorizontal, spacingVertical, false));

        // the following will change the look and feel of the toolbar to match the current design
        mRecyclerView.setToolbarBackgroundColor(ContextCompat.getColor(context, R.color.blue_medium));
        mRecyclerView.setToolbarSpinnerTextColor(ContextCompat.getColor(context, R.color.white));
        mRecyclerView.setToolbarSpinnerDrawable(R.drawable.arrow);
        mRecyclerView.setToolbarLeftAndRightPadding(
                getResources().getDimensionPixelSize(R.dimen.margin_medium) + spacingHorizontal,
                getResources().getDimensionPixelSize(R.dimen.margin_extra_large) + spacingHorizontal);

        // add a menu to the filtered recycler's toolbar
        if (!ReaderUtils.isLoggedOutReader()
                && (getPostListType() == ReaderPostListType.TAG_FOLLOWED || getPostListType() == ReaderPostListType.SEARCH_RESULTS)) {
            setupRecyclerToolbar();
        }

        mRecyclerView.setSwipeToRefreshEnabled(isSwipeToRefreshSupported());

        // bar that appears at top after new posts are loaded
        mNewPostsBar = rootView.findViewById(R.id.layout_new_posts);
        mNewPostsBar.setVisibility(View.GONE);
        mNewPostsBar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mRecyclerView.scrollRecycleViewToPosition(0);
                refreshPosts();
            }
        });

        // progress bar that appears when loading more posts
        mProgress = (ProgressBar) rootView.findViewById(R.id.progress_footer);
        mProgress.setVisibility(View.GONE);

        return rootView;
    }

    /*
     * adds a menu to the recycler's toolbar containing settings & search items - only called
     * for followed tags
     */
    private void setupRecyclerToolbar() {
        Menu menu = mRecyclerView.addToolbarMenu(R.menu.reader_list);
        mSettingsMenuItem = menu.findItem(R.id.menu_reader_settings);
        mSearchMenuItem = menu.findItem(R.id.menu_reader_search);

        mSettingsMenuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                ReaderActivityLauncher.showReaderSubs(getActivity());
                return true;
            }
        });

        mSearchView = (SearchView) mSearchMenuItem.getActionView();
        mSearchView.setQueryHint(getString(R.string.reader_hint_post_search));
        mSearchView.setSubmitButtonEnabled(false);
        mSearchView.setIconifiedByDefault(true);
        mSearchView.setIconified(true);

        // force the search view to take up as much horizontal space as possible (without this
        // it looks truncated on landscape)
        int maxWidth = DisplayUtils.getDisplayPixelWidth(getActivity());
        mSearchView.setMaxWidth(maxWidth);

        // this is hacky, but we want to change the SearchView's autocomplete to show suggestions
        // after a single character is typed, and there's no less hacky way to do this...
        View view = mSearchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
        if (view instanceof AutoCompleteTextView) {
            ((AutoCompleteTextView) view).setThreshold(1);
        }

        MenuItemCompat.setOnActionExpandListener(mSearchMenuItem, new MenuItemCompat.OnActionExpandListener() {
            @Override
            public boolean onMenuItemActionExpand(MenuItem item) {
                if (getPostListType() != ReaderPostListType.SEARCH_RESULTS) {
                    AnalyticsTracker.track(AnalyticsTracker.Stat.READER_SEARCH_LOADED);
                }
                resetPostAdapter(ReaderPostListType.SEARCH_RESULTS);
                showSearchMessage();
                mSettingsMenuItem.setVisible(false);
                return true;
            }

            @Override
            public boolean onMenuItemActionCollapse(MenuItem item) {
                hideSearchMessage();
                resetSearchSuggestionAdapter();
                mSettingsMenuItem.setVisible(true);
                mCurrentSearchQuery = null;

                // return to the followed tag that was showing prior to searching
                resetPostAdapter(ReaderPostListType.TAG_FOLLOWED);

                return true;
            }
        });

        mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
               @Override
               public boolean onQueryTextSubmit(String query) {
                   submitSearchQuery(query);
                   return true;
               }

               @Override
               public boolean onQueryTextChange(String newText) {
                   if (TextUtils.isEmpty(newText)) {
                       showSearchMessage();
                   } else {
                       populateSearchSuggestionAdapter(newText);
                   }
                   return true;
               }
           }
        );
    }

    /*
     * start the search service to search for posts matching the current query - the passed
     * offset is used during infinite scroll, pass zero for initial search
     */
    private void updatePostsInCurrentSearch(int offset) {
        ReaderSearchService.startService(getActivity(), mCurrentSearchQuery, offset);
    }

    private void submitSearchQuery(@NonNull String query) {
        if (!isAdded()) return;

        mSearchView.clearFocus(); // this will hide suggestions and the virtual keyboard
        hideSearchMessage();

        // remember this query for future suggestions
        String trimQuery = query != null ? query.trim() : "";
        ReaderSearchTable.addOrUpdateQueryString(trimQuery);

        // remove cached results for this search - search results are ephemeral so each search
        // should be treated as a "fresh" one
        ReaderTag searchTag = ReaderSearchService.getTagForSearchQuery(trimQuery);
        ReaderPostTable.deletePostsWithTag(searchTag);

        mPostAdapter.setCurrentTag(searchTag);
        mCurrentSearchQuery = trimQuery;
        updatePostsInCurrentSearch(0);

        // track that the user performed a search
        if (!trimQuery.equals("")) {
            Map<String, Object> properties = new HashMap<>();
            properties.put("query", trimQuery);
            AnalyticsTracker.track(AnalyticsTracker.Stat.READER_SEARCH_PERFORMED, properties);
        }
    }

    /*
     * reuse "empty" view to let user know what they're querying
     */
    private void showSearchMessage() {
        if (!isAdded()) return;

        // clear posts so only the empty view is visible
        getPostAdapter().clear();

        setEmptyTitleAndDescription(false);
        showEmptyView();
    }

    private void hideSearchMessage() {
        hideEmptyView();
    }

    /*
     * create and assign the suggestion adapter for the search view
     */
    private void createSearchSuggestionAdapter() {
        mSearchSuggestionAdapter = new ReaderSearchSuggestionAdapter(getActivity());
        mSearchView.setSuggestionsAdapter(mSearchSuggestionAdapter);

        mSearchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
            @Override
            public boolean onSuggestionSelect(int position) {
                return false;
            }

            @Override
            public boolean onSuggestionClick(int position) {
                String query = mSearchSuggestionAdapter.getSuggestion(position);
                if (!TextUtils.isEmpty(query)) {
                    mSearchView.setQuery(query, true);
                }
                return true;
            }
        });
    }

    private void populateSearchSuggestionAdapter(String query) {
        if (mSearchSuggestionAdapter == null) {
            createSearchSuggestionAdapter();
        }
        mSearchSuggestionAdapter.setFilter(query);
    }

    private void resetSearchSuggestionAdapter() {
        mSearchView.setSuggestionsAdapter(null);
        mSearchSuggestionAdapter = null;
    }

    /*
     * is the search input showing?
     */
    private boolean isSearchViewExpanded() {
        return mSearchView != null && !mSearchView.isIconified();
    }

    private boolean isSearchViewEmpty() {
        return mSearchView != null && mSearchView.getQuery().length() == 0;
    }

    @SuppressWarnings("unused")
    public void onEventMainThread(ReaderEvents.SearchPostsStarted event) {
        if (!isAdded()) return;

        UpdateAction updateAction = event.getOffset() == 0 ? UpdateAction.REQUEST_NEWER : UpdateAction.REQUEST_OLDER;
        setIsUpdating(true, updateAction);
        setEmptyTitleAndDescription(false);
    }

    @SuppressWarnings("unused")
    public void onEventMainThread(ReaderEvents.SearchPostsEnded event) {
        if (!isAdded()) return;

        UpdateAction updateAction = event.getOffset() == 0 ? UpdateAction.REQUEST_NEWER : UpdateAction.REQUEST_OLDER;
        setIsUpdating(false, updateAction);

        // load the results if the search succeeded and it's the current search - note that success
        // means the search didn't fail, not necessarily that is has results - which is fine because
        // if there aren't results then refreshing will show the empty message
        if (event.didSucceed()
                && getPostListType() == ReaderPostListType.SEARCH_RESULTS
                && event.getQuery().equals(mCurrentSearchQuery)) {
            refreshPosts();
        }
    }

    /*
     * called when user taps follow item in popup menu for a post
     */
    private void toggleFollowStatusForPost(final ReaderPost post) {
        if (post == null
                || !hasPostAdapter()
                || !NetworkUtils.checkConnection(getActivity())) {
            return;
        }

        final boolean isAskingToFollow = !ReaderPostTable.isPostFollowed(post);

        ReaderActions.ActionListener actionListener = new ReaderActions.ActionListener() {
            @Override
            public void onActionResult(boolean succeeded) {
                if (isAdded() && !succeeded) {
                    int resId = (isAskingToFollow ? R.string.reader_toast_err_follow_blog : R.string.reader_toast_err_unfollow_blog);
                    ToastUtils.showToast(getActivity(), resId);
                    getPostAdapter().setFollowStatusForBlog(post.blogId, !isAskingToFollow);
                }
            }
        };

        if (ReaderBlogActions.followBlogForPost(post, isAskingToFollow, actionListener)) {
            getPostAdapter().setFollowStatusForBlog(post.blogId, isAskingToFollow);
        }
    }

    /*
     * blocks the blog associated with the passed post and removes all posts in that blog
     * from the adapter
     */
    private void blockBlogForPost(final ReaderPost post) {
        if (post == null
                || !isAdded()
                || !hasPostAdapter()
                || !NetworkUtils.checkConnection(getActivity())) {
            return;
        }

        ReaderActions.ActionListener actionListener = new ReaderActions.ActionListener() {
            @Override
            public void onActionResult(boolean succeeded) {
                if (!succeeded && isAdded()) {
                    ToastUtils.showToast(getActivity(), R.string.reader_toast_err_block_blog, ToastUtils.Duration.LONG);
                }
            }
        };

        // perform call to block this blog - returns list of posts deleted by blocking so
        // they can be restored if the user undoes the block
        final BlockedBlogResult blockResult = ReaderBlogActions.blockBlogFromReader(post.blogId, actionListener);
        // Only pass the blogID if available. Do not track feedID
        AnalyticsUtils.trackWithBlogDetails(
                AnalyticsTracker.Stat.READER_BLOG_BLOCKED,
                mCurrentBlogId != 0 ? mCurrentBlogId : null
        );

        // remove posts in this blog from the adapter
        getPostAdapter().removePostsInBlog(post.blogId);

        // show the undo snackbar enabling the user to undo the block
        View.OnClickListener undoListener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ReaderBlogActions.undoBlockBlogFromReader(blockResult);
                refreshPosts();
            }
        };
        Snackbar.make(getView(), getString(R.string.reader_toast_blog_blocked), Snackbar.LENGTH_LONG)
                .setAction(R.string.undo, undoListener)
                .show();
    }

    /*
     * box/pages animation that appears when loading an empty list
     */
    private boolean shouldShowBoxAndPagesAnimation() {
        return getPostListType().isTagType();
    }

    private void startBoxAndPagesAnimation() {
        if (!isAdded()) return;

        ImageView page1 = (ImageView) mEmptyView.findViewById(R.id.empty_tags_box_page1);
        ImageView page2 = (ImageView) mEmptyView.findViewById(R.id.empty_tags_box_page2);
        ImageView page3 = (ImageView) mEmptyView.findViewById(R.id.empty_tags_box_page3);

        page1.startAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.box_with_pages_slide_up_page1));
        page2.startAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.box_with_pages_slide_up_page2));
        page3.startAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.box_with_pages_slide_up_page3));
    }

    private void setEmptyTitleAndDescription(boolean requestFailed) {
        if (!isAdded()) return;

        String title;
        String description = null;

        if (!NetworkUtils.isNetworkAvailable(getActivity())) {
            title = getString(R.string.reader_empty_posts_no_connection);
        } else if (requestFailed) {
            title = getString(R.string.reader_empty_posts_request_failed);
        } else if (isUpdating() && getPostListType() != ReaderPostListType.SEARCH_RESULTS) {
            title = getString(R.string.reader_empty_posts_in_tag_updating);
        } else {
            switch (getPostListType()) {
                case TAG_FOLLOWED:
                    if (getCurrentTag().isFollowedSites()) {
                        if (ReaderBlogTable.hasFollowedBlogs()) {
                            title = getString(R.string.reader_empty_followed_blogs_no_recent_posts_title);
                            description = getString(R.string.reader_empty_followed_blogs_no_recent_posts_description);
                        } else {
                            title = getString(R.string.reader_empty_followed_blogs_title);
                            description = getString(R.string.reader_empty_followed_blogs_description);
                        }
                    } else if (getCurrentTag().isPostsILike()) {
                        title = getString(R.string.reader_empty_posts_liked);
                    } else if (getCurrentTag().isListTopic()) {
                        title = getString(R.string.reader_empty_posts_in_custom_list);
                    } else {
                        title = getString(R.string.reader_empty_posts_in_tag);
                    }
                    break;

                case BLOG_PREVIEW:
                    title = getString(R.string.reader_empty_posts_in_blog);
                    break;

                case SEARCH_RESULTS:
                    if (isSearchViewEmpty() || TextUtils.isEmpty(mCurrentSearchQuery)) {
                        title = getString(R.string.reader_label_post_search_explainer);
                    } else if (isUpdating()) {
                        title = getString(R.string.reader_label_post_search_running);
                    } else {
                        title = getString(R.string.reader_empty_posts_in_search_title);
                        String formattedQuery = "<em>" + mCurrentSearchQuery + "</em>";
                        description = String.format(getString(R.string.reader_empty_posts_in_search_description), formattedQuery);
                    }
                    break;

                default:
                    title = getString(R.string.reader_empty_posts_in_tag);
                    break;
            }
        }

        setEmptyTitleAndDescription(title, description);
    }

    private void setEmptyTitleAndDescription(@NonNull String title, String description) {
        if (!isAdded()) return;

        TextView titleView = (TextView) mEmptyView.findViewById(R.id.title_empty);
        titleView.setText(title);

        TextView descriptionView = (TextView) mEmptyView.findViewById(R.id.description_empty);
        if (description == null) {
            descriptionView.setVisibility(View.INVISIBLE);
        } else {
            if (description.contains("<") && description.contains(">")) {
                descriptionView.setText(Html.fromHtml(description));
            } else {
                descriptionView.setText(description);
            }
            descriptionView.setVisibility(View.VISIBLE);
        }

        mEmptyViewBoxImages.setVisibility(shouldShowBoxAndPagesAnimation() ? View.VISIBLE : View.GONE);
    }

    private void showEmptyView() {
        if (isAdded()) {
            mEmptyView.setVisibility(View.VISIBLE);
        }
    }

    private void hideEmptyView() {
        if (isAdded()) {
            mEmptyView.setVisibility(View.GONE);
        }
    }

    /*
     * called by post adapter when data has been loaded
     */
    private final ReaderInterfaces.DataLoadedListener mDataLoadedListener = new ReaderInterfaces.DataLoadedListener() {
        @Override
        public void onDataLoaded(boolean isEmpty) {
            if (!isAdded()) {
                return;
            }
            mRecyclerView.setRefreshing(false);
            if (isEmpty) {
                setEmptyTitleAndDescription(false);
                showEmptyView();
                if (shouldShowBoxAndPagesAnimation()) {
                    startBoxAndPagesAnimation();
                }
            } else {
                hideEmptyView();
                if (mRestorePosition > 0) {
                    AppLog.d(T.READER, "reader post list > restoring position");
                    mRecyclerView.scrollRecycleViewToPosition(mRestorePosition);
                }
            }
            mRestorePosition = 0;
        }
    };

    /*
     * called by post adapter to load older posts when user scrolls to the last post
     */
    private final ReaderActions.DataRequestedListener mDataRequestedListener = new ReaderActions.DataRequestedListener() {
        @Override
        public void onRequestData() {
            // skip if update is already in progress
            if (isUpdating()) {
                return;
            }

            // request older posts unless we already have the max # to show
            switch (getPostListType()) {
                case TAG_FOLLOWED:
                case TAG_PREVIEW:
                    if (ReaderPostTable.getNumPostsWithTag(mCurrentTag) < ReaderConstants.READER_MAX_POSTS_TO_DISPLAY) {
                        // request older posts
                        updatePostsWithTag(getCurrentTag(), UpdateAction.REQUEST_OLDER);
                        AnalyticsTracker.track(AnalyticsTracker.Stat.READER_INFINITE_SCROLL);
                    }
                    break;

                case BLOG_PREVIEW:
                    int numPosts;
                    if (mCurrentFeedId != 0) {
                        numPosts = ReaderPostTable.getNumPostsInFeed(mCurrentFeedId);
                    } else {
                        numPosts = ReaderPostTable.getNumPostsInBlog(mCurrentBlogId);
                    }
                    if (numPosts < ReaderConstants.READER_MAX_POSTS_TO_DISPLAY) {
                        updatePostsInCurrentBlogOrFeed(UpdateAction.REQUEST_OLDER);
                        AnalyticsTracker.track(AnalyticsTracker.Stat.READER_INFINITE_SCROLL);
                    }
                    break;

                case SEARCH_RESULTS:
                    ReaderTag searchTag = ReaderSearchService.getTagForSearchQuery(mCurrentSearchQuery);
                    int offset = ReaderPostTable.getNumPostsWithTag(searchTag);
                    if (offset < ReaderConstants.READER_MAX_POSTS_TO_DISPLAY) {
                        updatePostsInCurrentSearch(offset);
                        AnalyticsTracker.track(AnalyticsTracker.Stat.READER_INFINITE_SCROLL);
                    }
                    break;
            }
        }
    };

    private ReaderPostAdapter getPostAdapter() {
        if (mPostAdapter == null) {
            AppLog.d(T.READER, "reader post list > creating post adapter");
            Context context = WPActivityUtils.getThemedContext(getActivity());
            mPostAdapter = new ReaderPostAdapter(context, getPostListType());
            mPostAdapter.setOnPostSelectedListener(this);
            mPostAdapter.setOnTagSelectedListener(this);
            mPostAdapter.setOnPostPopupListener(this);
            mPostAdapter.setOnDataLoadedListener(mDataLoadedListener);
            mPostAdapter.setOnDataRequestedListener(mDataRequestedListener);
            if (getActivity() instanceof ReaderSiteHeaderView.OnBlogInfoLoadedListener) {
                mPostAdapter.setOnBlogInfoLoadedListener((ReaderSiteHeaderView.OnBlogInfoLoadedListener) getActivity());
            }
            if (getPostListType().isTagType()) {
                mPostAdapter.setCurrentTag(getCurrentTag());
            } else if (getPostListType() == ReaderPostListType.BLOG_PREVIEW) {
                mPostAdapter.setCurrentBlogAndFeed(mCurrentBlogId, mCurrentFeedId);
            } else if (getPostListType() == ReaderPostListType.SEARCH_RESULTS) {
                ReaderTag searchTag = ReaderSearchService.getTagForSearchQuery(mCurrentSearchQuery);
                mPostAdapter.setCurrentTag(searchTag);
            }
        }
        return mPostAdapter;
    }

    private boolean hasPostAdapter() {
        return (mPostAdapter != null);
    }

    private boolean isPostAdapterEmpty() {
        return (mPostAdapter == null || mPostAdapter.isEmpty());
    }

    private boolean isCurrentTag(final ReaderTag tag) {
        return ReaderTag.isSameTag(tag, mCurrentTag);
    }
    private boolean isCurrentTagName(String tagName) {
        return (tagName != null && tagName.equalsIgnoreCase(getCurrentTagName()));
    }

    private ReaderTag getCurrentTag() {
        return mCurrentTag;
    }

    private String getCurrentTagName() {
        return (mCurrentTag != null ? mCurrentTag.getTagSlug() : "");
    }

    private boolean hasCurrentTag() {
        return mCurrentTag != null;
    }

    private void setCurrentTag(final ReaderTag tag) {
        if (tag == null) {
            return;
        }

        // skip if this is already the current tag and the post adapter is already showing it
        if (isCurrentTag(tag)
                && hasPostAdapter()
                && getPostAdapter().isCurrentTag(tag)) {
            return;
        }

        mCurrentTag = tag;

        switch (getPostListType()) {
            case TAG_FOLLOWED:
                // remember this as the current tag if viewing followed tag
                AppPrefs.setReaderTag(tag);
                break;
            case TAG_PREVIEW:
                mTagPreviewHistory.push(tag.getTagSlug());
                break;
        }

        getPostAdapter().setCurrentTag(tag);
        hideNewPostsBar();
        showLoadingProgress(false);

        updateCurrentTagIfTime();
    }

    /*
     * called by the activity when user hits the back button - returns true if the back button
     * is handled here and should be ignored by the activity
     */
    @Override
    public boolean onActivityBackPressed() {
        if (isSearchViewExpanded()) {
            mSearchMenuItem.collapseActionView();
            return true;
        } else if (goBackInTagHistory()) {
            return true;
        } else {
            return false;
        }
    }

    /*
    * when previewing posts with a specific tag, a history of previewed tags is retained so
    * the user can navigate back through them - this is faster and requires less memory
    * than creating a new fragment for each previewed tag
    */
    private boolean goBackInTagHistory() {
        if (mTagPreviewHistory.empty()) {
            return false;
        }

        String tagName = mTagPreviewHistory.pop();
        if (isCurrentTagName(tagName)) {
            if (mTagPreviewHistory.empty()) {
                return false;
            }
            tagName = mTagPreviewHistory.pop();
        }

        ReaderTag newTag = ReaderUtils.getTagFromTagName(tagName, ReaderTagType.FOLLOWED);
        setCurrentTag(newTag);

        return true;
    }

    /*
     * load tags on which the main data will be filtered
     */
    private void loadTags(FilteredRecyclerView.FilterCriteriaAsyncLoaderListener listener) {
        new LoadTagsTask(listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    /*
     * refresh adapter so latest posts appear
     */
    private void refreshPosts() {
        hideNewPostsBar();
        if (hasPostAdapter()) {
            getPostAdapter().refresh();
        }
    }

    /*
     * same as above but clears posts before refreshing
     */
    private void reloadPosts() {
        hideNewPostsBar();
        if (hasPostAdapter()) {
            getPostAdapter().reload();
        }
    }

    /*
     * reload the list of tags for the dropdown filter
     */
    private void reloadTags() {
        if (isAdded() && mRecyclerView != null) {
            mRecyclerView.refreshFilterCriteriaOptions();
        }
    }

    /*
     * get posts for the current blog from the server
     */
    private void updatePostsInCurrentBlogOrFeed(final UpdateAction updateAction) {
        if (!NetworkUtils.isNetworkAvailable(getActivity())) {
            AppLog.i(T.READER, "reader post list > network unavailable, canceled blog update");
            return;
        }
        if (mCurrentFeedId != 0) {
            ReaderPostService.startServiceForFeed(getActivity(), mCurrentFeedId, updateAction);
        } else {
            ReaderPostService.startServiceForBlog(getActivity(), mCurrentBlogId, updateAction);
        }
    }

    @SuppressWarnings("unused")
    public void onEventMainThread(ReaderEvents.UpdatePostsStarted event) {
        if (!isAdded()) return;

        setIsUpdating(true, event.getAction());
        setEmptyTitleAndDescription(false);
    }

    @SuppressWarnings("unused")
    public void onEventMainThread(ReaderEvents.UpdatePostsEnded event) {
        if (!isAdded()) return;

        setIsUpdating(false, event.getAction());
        if (event.getReaderTag() != null && !isCurrentTag(event.getReaderTag())) {
            return;
        }

        // don't show new posts if user is searching - posts will automatically
        // appear when search is exited
        if (isSearchViewExpanded()
                || getPostListType() == ReaderPostListType.SEARCH_RESULTS) {
            return;
        }

        // determine whether to show the "new posts" bar - when this is shown, the newly
        // downloaded posts aren't displayed until the user taps the bar - only appears
        // when there are new posts in a followed tag and the user has scrolled the list
        // beyond the first post
        if (event.getResult() == ReaderActions.UpdateResult.HAS_NEW
                && event.getAction() == UpdateAction.REQUEST_NEWER
                && getPostListType() == ReaderPostListType.TAG_FOLLOWED
                && !isPostAdapterEmpty()
                && (!isAdded() || !mRecyclerView.isFirstItemVisible())) {
            showNewPostsBar();
        } else if (event.getResult().isNewOrChanged()) {
            refreshPosts();
        } else {
            boolean requestFailed = (event.getResult() == ReaderActions.UpdateResult.FAILED);
            setEmptyTitleAndDescription(requestFailed);
            // if we requested posts in order to fill a gap but the request failed or didn't
            // return any posts, reload the adapter so the gap marker is reset (hiding its
            // progress bar)
            if (event.getAction() == UpdateAction.REQUEST_OLDER_THAN_GAP) {
                reloadPosts();
            }
        }
    }

    /*
     * get latest posts for this tag from the server
     */
    private void updatePostsWithTag(ReaderTag tag, UpdateAction updateAction) {
        if (!isAdded()) return;

        if (!NetworkUtils.isNetworkAvailable(getActivity())) {
            AppLog.i(T.READER, "reader post list > network unavailable, canceled tag update");
            return;
        }
        if (tag == null) {
            AppLog.w(T.READER, "null tag passed to updatePostsWithTag");
            return;
        }
        AppLog.d(T.READER, "reader post list > updating tag " + tag.getTagNameForLog() + ", updateAction=" + updateAction.name());
        ReaderPostService.startServiceForTag(getActivity(), tag, updateAction);
    }

    private void updateCurrentTag() {
        updatePostsWithTag(getCurrentTag(), UpdateAction.REQUEST_NEWER);
    }

    /*
     * update the current tag if it's time to do so - note that the check is done in the
     * background since it can be expensive and this is called when the fragment is
     * resumed, which on slower devices can result in a janky experience
     */
    private void updateCurrentTagIfTime() {
        if (!isAdded() || !hasCurrentTag()) {
            return;
        }
        new Thread() {
            @Override
            public void run() {
                if (ReaderTagTable.shouldAutoUpdateTag(getCurrentTag()) && isAdded()) {
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            updateCurrentTag();
                        }
                    });
                }
            }
        }.start();
    }

    private boolean isUpdating() {
        return mIsUpdating;
    }

    /*
    * show/hide progress bar which appears at the bottom of the activity when loading more posts
    */
    private void showLoadingProgress(boolean showProgress) {
        if (isAdded() && mProgress != null) {
            if (showProgress) {
                mProgress.bringToFront();
                mProgress.setVisibility(View.VISIBLE);
            } else {
                mProgress.setVisibility(View.GONE);
            }
        }
    }

    private void setIsUpdating(boolean isUpdating, UpdateAction updateAction) {
        if (!isAdded() || mIsUpdating == isUpdating) {
            return;
        }

        if (updateAction == UpdateAction.REQUEST_OLDER) {
            // show/hide progress bar at bottom if these are older posts
            showLoadingProgress(isUpdating);
        } else if (isUpdating && isPostAdapterEmpty()) {
            // show swipe-to-refresh if update started and no posts are showing
            mRecyclerView.setRefreshing(true);
        } else if (!isUpdating) {
            // hide swipe-to-refresh progress if update is complete
            mRecyclerView.setRefreshing(false);
        }
        mIsUpdating = isUpdating;

        // if swipe-to-refresh isn't active, keep it disabled during an update - this prevents
        // doing a refresh while another update is already in progress
        if (mRecyclerView != null && !mRecyclerView.isRefreshing()) {
            mRecyclerView.setSwipeToRefreshEnabled(!isUpdating && isSwipeToRefreshSupported());
        }
    }

    /*
     * swipe-to-refresh isn't supported for search results since they're really brief snapshots
     * and are unlikely to show new posts due to the way they're sorted
     */
    private boolean isSwipeToRefreshSupported() {
        return getPostListType() != ReaderPostListType.SEARCH_RESULTS;
    }

    /*
     * bar that appears at the top when new posts have been retrieved
     */
    private boolean isNewPostsBarShowing() {
        return (mNewPostsBar != null && mNewPostsBar.getVisibility() == View.VISIBLE);
    }

    /*
     * scroll listener assigned to the recycler when the "new posts" bar is shown to hide
     * it upon scrolling
     */
    private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            hideNewPostsBar();
        }
    };

    private void showNewPostsBar() {
        if (!isAdded() || isNewPostsBarShowing()) {
            return;
        }

        AniUtils.startAnimation(mNewPostsBar, R.anim.reader_top_bar_in);
        mNewPostsBar.setVisibility(View.VISIBLE);

        // assign the scroll listener to hide the bar when the recycler is scrolled, but don't assign
        // it right away since the user may be scrolling when the bar appears (which would cause it
        // to disappear as soon as it's displayed)
        mRecyclerView.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (isAdded() && isNewPostsBarShowing()) {
                    mRecyclerView.addOnScrollListener(mOnScrollListener);
                }
            }
        }, 1000L);

        // remove the gap marker if it's showing, since it's no longer valid
        getPostAdapter().removeGapMarker();
    }

    private void hideNewPostsBar() {
        if (!isAdded() || !isNewPostsBarShowing() || mIsAnimatingOutNewPostsBar) {
            return;
        }

        mIsAnimatingOutNewPostsBar = true;

        // remove the onScrollListener assigned in showNewPostsBar()
        mRecyclerView.removeOnScrollListener(mOnScrollListener);

        Animation.AnimationListener listener = new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) { }
            @Override
            public void onAnimationEnd(Animation animation) {
                if (isAdded()) {
                    mNewPostsBar.setVisibility(View.GONE);
                    mIsAnimatingOutNewPostsBar = false;
                }
            }
            @Override
            public void onAnimationRepeat(Animation animation) { }
        };
        AniUtils.startAnimation(mNewPostsBar, R.anim.reader_top_bar_out, listener);
    }

    /*
     * are we showing all posts with a specific tag (followed or previewed), or all
     * posts in a specific blog?
     */
    private ReaderPostListType getPostListType() {
        return (mPostListType != null ? mPostListType : ReaderTypes.DEFAULT_POST_LIST_TYPE);
    }

    /*
     * called from adapter when user taps a post
     */
    @Override
    public void onPostSelected(ReaderPost post) {
        if (!isAdded() || post == null) return;

        // "discover" posts that highlight another post should open the original (source) post when tapped
        if (post.isDiscoverPost()) {
            ReaderPostDiscoverData discoverData = post.getDiscoverData();
            if (discoverData != null && discoverData.getDiscoverType() == ReaderPostDiscoverData.DiscoverType.EDITOR_PICK) {
                if (discoverData.getBlogId() != 0 && discoverData.getPostId() != 0) {
                    ReaderActivityLauncher.showReaderPostDetail(
                            getActivity(),
                            discoverData.getBlogId(),
                            discoverData.getPostId());
                    return;
                } else if (discoverData.hasPermalink()) {
                    // if we don't have a blogId/postId, we sadly resort to showing the post
                    // in a WebView activity - this will happen for non-JP self-hosted
                    ReaderActivityLauncher.openUrl(getActivity(), discoverData.getPermaLink());
                    return;
                }
            }
        }

        // if this is a cross-post, we want to show the original post
        if (post.isXpost()) {
            ReaderActivityLauncher.showReaderPostDetail(getActivity(), post.xpostBlogId, post.xpostPostId);
            return;
        }

        ReaderPostListType type = getPostListType();

        switch (type) {
            case TAG_FOLLOWED:
            case TAG_PREVIEW:
                ReaderActivityLauncher.showReaderPostPagerForTag(
                        getActivity(),
                        getCurrentTag(),
                        getPostListType(),
                        post.blogId,
                        post.postId);
                break;
            case BLOG_PREVIEW:
                ReaderActivityLauncher.showReaderPostPagerForBlog(
                        getActivity(),
                        post.blogId,
                        post.postId);
                break;
            case SEARCH_RESULTS:
                AnalyticsUtils.trackWithReaderPostDetails(AnalyticsTracker.Stat.READER_SEARCH_RESULT_TAPPED, post);
                ReaderActivityLauncher.showReaderPostDetail(getActivity(), post.blogId, post.postId);
                break;
        }
    }

    /*
     * called from adapter when user taps a tag on a post to display tag preview
     */
    @Override
    public void onTagSelected(String tagName) {
        if (!isAdded()) return;

        ReaderTag tag = ReaderUtils.getTagFromTagName(tagName, ReaderTagType.FOLLOWED);
        if (getPostListType().equals(ReaderPostListType.TAG_PREVIEW)) {
            // user is already previewing a tag, so change current tag in existing preview
            setCurrentTag(tag);
        } else {
            // user isn't previewing a tag, so open in tag preview
            ReaderActivityLauncher.showReaderTagPreview(getActivity(), tag);
        }
    }

    /*
     * called when user selects a tag from the tag toolbar
     */
    private void onTagChanged(ReaderTag tag) {
        if (!isAdded() || isCurrentTag(tag)) return;

        trackTagLoaded(tag);
        AppLog.d(T.READER, String.format("reader post list > tag %s displayed", tag.getTagNameForLog()));
        setCurrentTag(tag);
    }

    private void trackTagLoaded(ReaderTag tag) {
        AnalyticsTracker.Stat stat = null;

        if (tag.isDiscover()) {
            stat = AnalyticsTracker.Stat.READER_DISCOVER_VIEWED;
        } else if (tag.isTagTopic()) {
            stat = AnalyticsTracker.Stat.READER_TAG_LOADED;
        } else if (tag.isListTopic()) {
            stat = AnalyticsTracker.Stat.READER_LIST_LOADED;
        }

        if (stat == null) return;

        Map<String, String> properties = new HashMap<>();
        properties.put("tag", tag.getTagSlug());

        AnalyticsTracker.track(stat, properties);
    }

    /*
     * called when user taps "..." icon next to a post
     */
    @Override
    public void onShowPostPopup(View view, final ReaderPost post) {
        if (view == null || post == null || !isAdded()) return;

        Context context = view.getContext();
        final ListPopupWindow listPopup = new ListPopupWindow(context);
        listPopup.setAnchorView(view);
        listPopup.setWidth(context.getResources().getDimensionPixelSize(R.dimen.menu_item_width));
        listPopup.setModal(true);

        List<Integer> menuItems = new ArrayList<>();
        boolean isFollowed = ReaderPostTable.isPostFollowed(post);
        if (isFollowed) {
            menuItems.add(ReaderMenuAdapter.ITEM_UNFOLLOW);
        } else {
            menuItems.add(ReaderMenuAdapter.ITEM_FOLLOW);
        }
        if (getPostListType() == ReaderPostListType.TAG_FOLLOWED) {
            menuItems.add(ReaderMenuAdapter.ITEM_BLOCK);
        }
        listPopup.setAdapter(new ReaderMenuAdapter(context, menuItems));
        listPopup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (!isAdded()) return;

                listPopup.dismiss();
                switch((int) id) {
                    case ReaderMenuAdapter.ITEM_FOLLOW:
                    case ReaderMenuAdapter.ITEM_UNFOLLOW:
                        toggleFollowStatusForPost(post);
                        break;
                    case ReaderMenuAdapter.ITEM_BLOCK:
                        blockBlogForPost(post);
                        break;
                }
            }
        });
        listPopup.show();
    }

    /*
     * purge reader db if it hasn't been done yet
     */
    private void purgeDatabaseIfNeeded() {
        if (!mHasPurgedReaderDb) {
            AppLog.d(T.READER, "reader post list > purging database");
            mHasPurgedReaderDb = true;
            ReaderDatabase.purgeAsync();
        }
    }

    /*
     * start background service to get the latest followed tags and blogs if it's time to do so
     */
    private void updateFollowedTagsAndBlogsIfNeeded() {
        if (mLastAutoUpdateDt != null) {
            int minutesSinceLastUpdate = DateTimeUtils.minutesBetween(mLastAutoUpdateDt, new Date());
            if (minutesSinceLastUpdate < 120) {
                return;
            }
        }

        AppLog.d(T.READER, "reader post list > updating tags and blogs");
        mLastAutoUpdateDt = new Date();
        ReaderUpdateService.startService(getActivity(), EnumSet.of(UpdateTask.TAGS, UpdateTask.FOLLOWED_BLOGS));
    }

    @Override
    public void onScrollToTop() {
        if (isAdded() && getCurrentPosition() > 0) {
            mRecyclerView.smoothScrollToPosition(0);
            mRecyclerView.showToolbar();
        }
    }

    public static void resetLastUpdateDate() {
        mLastAutoUpdateDt = null;
    }

    private class LoadTagsTask extends AsyncTask<Void, Void, ReaderTagList> {

        private final FilteredRecyclerView.FilterCriteriaAsyncLoaderListener mFilterCriteriaLoaderListener;

        public LoadTagsTask(FilteredRecyclerView.FilterCriteriaAsyncLoaderListener listener){
            mFilterCriteriaLoaderListener = listener;
        }

        @Override
        protected ReaderTagList doInBackground(Void... voids) {
            ReaderTagList tagList = ReaderTagTable.getDefaultTags();
            tagList.addAll(ReaderTagTable.getCustomListTags());
            tagList.addAll(ReaderTagTable.getFollowedTags());
            return tagList;
        }

        @Override
        protected void onPostExecute(ReaderTagList tagList) {
            if (tagList != null && !tagList.isSameList(mTags)) {
                mTags.clear();
                mTags.addAll(tagList);
                if (mFilterCriteriaLoaderListener != null)
                    //noinspection unchecked
                    mFilterCriteriaLoaderListener.onFilterCriteriasLoaded((List)mTags);
            }
        }
    }

}

