com.none.tom.simplerssreader.activity.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.none.tom.simplerssreader.activity.MainActivity.java

Source

// Copyright (c) 2017-2018, Tom Geiselmann
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
// and associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY,WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package com.none.tom.simplerssreader.activity;

import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.LoaderManager;
import android.content.Intent;
import android.content.Loader;
import android.content.res.Resources;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.ActionBar;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;

import com.none.tom.simplerssreader.R;
import com.none.tom.simplerssreader.activity.base.BaseActivity;
import com.none.tom.simplerssreader.feed.CurrentFeed;
import com.none.tom.simplerssreader.feed.SavedEntries;
import com.none.tom.simplerssreader.fragment.ExportSubscriptionsFragment;
import com.none.tom.simplerssreader.fragment.FeedSubscriptionBaseFragment;
import com.none.tom.simplerssreader.fragment.FeedSubscriptionEditFragment;
import com.none.tom.simplerssreader.fragment.InitialSetupFragment;
import com.none.tom.simplerssreader.fragment.LoadCurrentFeedFragment;
import com.none.tom.simplerssreader.fragment.FeedSubscriptionFragment;
import com.none.tom.simplerssreader.fragment.SavedEntriesDeleteEntriesFragment;
import com.none.tom.simplerssreader.fragment.SavedEntriesFragment;
import com.none.tom.simplerssreader.fragment.CurrentFeedFragment;
import com.none.tom.simplerssreader.fragment.SavedEntriesSavePasswordFragment;
import com.none.tom.simplerssreader.fragment.UnsubscribeFromFeedsFragment;
import com.none.tom.simplerssreader.fragment.FeedSubscriptionsFragment;
import com.none.tom.simplerssreader.loader.IsFeedUpdateAvailableLoader;
import com.none.tom.simplerssreader.loader.ImportSubscriptionsLoader;
import com.none.tom.simplerssreader.loader.SavedEntriesSaveLoader;
import com.none.tom.simplerssreader.utils.ExportUtils;
import com.none.tom.simplerssreader.utils.SnackbarUtils;
import com.none.tom.simplerssreader.utils.ErrorHandler;
import com.none.tom.simplerssreader.utils.SearchResults;
import com.none.tom.simplerssreader.utils.SharedPrefUtils;
import com.none.tom.simplerssreader.utils.SoftInputUtils;
import com.none.tom.simplerssreader.utils.ThemeUtils;
import com.none.tom.simplerssreader.utils.TypedValueUtils;
import com.none.tom.simplerssreader.view.HistoryAwareBottomNavigationView;
import com.rometools.rome.feed.synd.SyndEntry;

import org.joda.time.LocalDateTime;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.none.tom.simplerssreader.activity.Constants.ICON_ALPHA_LOW;
import static com.none.tom.simplerssreader.activity.Constants.ICON_ALPHA_NORMAL;
import static com.none.tom.simplerssreader.activity.Constants.INTENT_EXTRA_FONT_SIZE_CHANGED;
import static com.none.tom.simplerssreader.activity.Constants.INTENT_EXTRA_THEME_CHANGED;
import static com.none.tom.simplerssreader.utils.Constants.*;

public class MainActivity extends BaseActivity implements LoaderManager.LoaderCallbacks {
    private static final String KEY_FRAGMENT_TAG = "key_fragment_tag";
    private static final String KEY_IMPORT_SUBSCRIPTIONS = "key_import_subscriptions";
    private static final String KEY_ENTRY_URLS = "key_entry_urls";
    private static final String KEY_ENTRY_TITLES = "key_entry_titles";
    private static final String KEY_SEARCH_VIEW = "key_search_view";
    private static final String KEY_SEARCH_QUERY = "key_search_query";

    private boolean mNavigateBackNewCurrentFeed;
    private boolean mFeedSubscriptionsChanged;
    private boolean mLoadNewCurrentFeed;
    private boolean mIsCategoriesFilterApplied;
    private boolean mRetainCategories;

    private int[] mActionBarInsets;

    private List<Integer> mSelectedRecyclerViewPositions;

    private SearchResults mSearchResults;

    private HistoryAwareBottomNavigationView mBottomNavigationView;
    private android.view.ActionMode mActionMode;
    private EditText mSearchEditText;

    private CurrentFeedFragment mCurrentFeedFragment;
    private FeedSubscriptionsFragment mFeedSubscriptionsFragment;
    private SavedEntriesFragment mSavedEntriesFragment;
    private InitialSetupFragment mInitialSetupFragment;
    private LoadCurrentFeedFragment mLoadCurrentFeedFragment;

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

        setContentView(R.layout.activity_main);

        mBottomNavigationView = findViewById(R.id.ActivityMainBottomNavigationView);
        mBottomNavigationView
                .setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(@NonNull final MenuItem item) {
                        if (mActionMode != null) {
                            mActionMode.finish();
                        }

                        if (searchViewIsVisible()) {
                            searchViewHide();
                        }

                        getCurrentFeedFragment().finishLayoutRefreshing();

                        switch (item.getItemId()) {
                        case R.id.action_current_feed:
                            if (loadNewCurrentFeed() || getLoadCurrentFeedFragment().isLoadingOrFailed()) {
                                replaceFragment(getLoadCurrentFeedFragment(), true);
                            } else if (getSavedEntriesFragment().isAdded()) {
                                removeFragment(getSavedEntriesFragment(), false);
                                addFragment(getCurrentFeedFragment(), false, false);
                            } else {
                                replaceFragment(getCurrentFeedFragment(), true);
                            }
                            return true;
                        case R.id.action_feed_subscriptions:
                            if (getSavedEntriesFragment().isAdded()) {
                                removeFragment(getSavedEntriesFragment(), false);
                                addFragment(getFeedSubscriptionsFragment(), false, false);
                            } else {
                                replaceFragment(getFeedSubscriptionsFragment(), true);
                            }
                            return true;
                        case R.id.action_saved_entries:
                            replaceFragment(getSavedEntriesFragment(), false);
                            return true;
                        default:
                            return false;
                        }
                    }
                });

        mBottomNavigationView.setOnNavigationItemReselectedListener(
                new BottomNavigationView.OnNavigationItemReselectedListener() {
                    @Override
                    public void onNavigationItemReselected(@NonNull final MenuItem item) {
                        switch (item.getItemId()) {
                        case R.id.action_current_feed:
                            if (getCurrentFeedFragment().isVisible()) {
                                getCurrentFeedFragment().scrollTo(0);
                            }
                            break;
                        case R.id.action_feed_subscriptions:
                            if (getFeedSubscriptionsFragment().isVisible()) {
                                getFeedSubscriptionsFragment().scrollToTop();
                            }
                            break;
                        case R.id.action_saved_entries:
                            if (getSavedEntriesFragment().isVisible()) {
                                getSavedEntriesFragment().scrollToTop();
                            }
                            break;
                        default:
                            break;
                        }
                    }
                });

        final Intent intent = getIntent();

        if (!TextUtils.isEmpty(intent.getDataString())) {
            addSubscription(intent.getDataString(), true);
        } else if (savedInstanceState == null) {
            loadCurrentFeedOrShowInitialSetup();
        }
    }

    @Override
    public void onBackPressed() {
        if (searchViewIsVisible()) {
            searchViewHide();
        } else if (!navigateBackInFragmentBackStack()) {
            super.onBackPressed();
        }
    }

    @Override
    protected void onNewIntent(final Intent intent) {
        super.onNewIntent(intent);

        setIntent(intent);

        if (!TextUtils.isEmpty(intent.getDataString())) {
            addSubscription(intent.getDataString(), false);
        }
    }

    @Override
    public void onSaveInstanceState(final Bundle outState) {
        super.onSaveInstanceState(outState);

        final FragmentManager fm = getFragmentManager();

        if (fm.findFragmentByTag(CurrentFeedFragment.TAG) != null) {
            outState.putString(KEY_FRAGMENT_TAG, CurrentFeedFragment.TAG);
        } else if (fm.findFragmentByTag(FeedSubscriptionsFragment.TAG) != null) {
            outState.putString(KEY_FRAGMENT_TAG, FeedSubscriptionsFragment.TAG);
        } else if (fm.findFragmentByTag(SavedEntriesFragment.TAG) != null) {
            outState.putString(KEY_FRAGMENT_TAG, SavedEntriesFragment.TAG);
        } else if (fm.findFragmentByTag(InitialSetupFragment.TAG) != null) {
            outState.putString(KEY_FRAGMENT_TAG, InitialSetupFragment.TAG);
        } else if (fm.findFragmentByTag(LoadCurrentFeedFragment.TAG) != null) {
            outState.putString(KEY_FRAGMENT_TAG, LoadCurrentFeedFragment.TAG);
        }

        if (searchViewIsVisible()) {
            outState.putBoolean(KEY_SEARCH_VIEW, true);
            outState.putString(KEY_SEARCH_QUERY, searchViewGetQuery());
        }

        if (mActionMode != null) {
            mActionMode.finish();
        }
    }

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

        final String tag = savedInstanceState.getString(KEY_FRAGMENT_TAG);

        if (!TextUtils.isEmpty(tag) && tag.equals(InitialSetupFragment.TAG)) {
            mBottomNavigationView.setVisibility(View.GONE);
        }

        if (savedInstanceState.getBoolean(KEY_SEARCH_VIEW)) {
            searchViewShow(savedInstanceState.getString(KEY_SEARCH_QUERY));
        }
    }

    @Override
    protected void onActivityResult(final int requestCode, final int resultCode, final Intent resultData) {
        super.onActivityResult(requestCode, resultCode, resultData);

        switch (resultCode) {
        case RESULT_OK:
            switch (requestCode) {
            case REQUEST_CODE_IMPORT_SUBSCRIPTIONS:
                importSubscriptions(resultData.getData());
                break;
            case REQUEST_CODE_EXPORT_SUBSCRIPTIONS:
                exportSubscriptions(resultData.getData());
                break;
            case REQUEST_CODE_EXPORT_SAVED_ENTRIES:
                exportSavedEntries(resultData.getData(), MIME_TYPE_JSON);
                break;
            case REQUEST_CODE_SETTINGS:
                if (resultData.getBooleanExtra(INTENT_EXTRA_THEME_CHANGED, false)
                        || resultData.getBooleanExtra(INTENT_EXTRA_FONT_SIZE_CHANGED, false)) {
                    recreate();
                }
                break;
            }
            break;
        case RESULT_CANCELED:
            switch (requestCode) {
            case REQUEST_CODE_IMPORT_SUBSCRIPTIONS:
                if (isNotInInitialSetup()) {
                    FeedSubscriptionBaseFragment.getInstance().show(getSupportFragmentManager(),
                            FeedSubscriptionBaseFragment.TAG);
                }
                break;
            case REQUEST_CODE_EXPORT_SUBSCRIPTIONS:
                ExportSubscriptionsFragment.getInstance().show(getFragmentManager(),
                        ExportSubscriptionsFragment.TAG);
                break;
            default:
                break;
            }
            break;
        default:
            break;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main_action_bar, menu);

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(final Menu menu) {
        final MenuItem update = menu.findItem(R.id.action_update);
        final MenuItem sortEntries = menu.findItem(R.id.action_sort_entries);
        final MenuItem exportSubscriptions = menu.findItem(R.id.action_export_subscriptions);
        final MenuItem exportSavedEntries = menu.findItem(R.id.action_export_saved_entries);
        final MenuItem filter = menu.findItem(R.id.action_filter_by_categories);
        final MenuItem search = menu.findItem(R.id.action_search);
        final MenuItem settings = menu.findItem(R.id.action_settings);
        final MenuItem category = menu.findItem(R.id.action_filter_subscriptions_by_category);

        final boolean searchViewVisible = searchViewIsVisible();

        if (isNotInInitialSetup()) {
            if (getLoadCurrentFeedFragment().isAdded()) {
                toggleMenuItemVisibility(search, false);
                toggleMenuItemVisibility(sortEntries, false);
                toggleMenuItemVisibility(category, false);
                toggleMenuItemVisibility(exportSubscriptions, false);
                toggleMenuItemVisibility(exportSavedEntries, false);
            } else if (getCurrentFeedFragment().isAdded()) {
                toggleMenuItemVisibility(sortEntries, false);
                toggleMenuItemVisibility(category, false);
                toggleMenuItemVisibility(exportSubscriptions, false);
                toggleMenuItemVisibility(exportSavedEntries, false);

                if (!searchViewVisible) {
                    toggleMenuItemVisibility(update, true);
                    toggleMenuItemVisibility(search, true);
                }

                if (CurrentFeed.isRSSFeed() && CurrentFeed.isCategoriesAvailable() && !searchViewVisible) {
                    toggleMenuItemVisibility(filter, true);
                }
            } else if (getFeedSubscriptionsFragment().isAdded()) {
                toggleMenuItemVisibility(update, false);
                toggleMenuItemVisibility(sortEntries, false);
                toggleMenuItemVisibility(filter, false);
                toggleMenuItemVisibility(exportSavedEntries, false);

                if (!searchViewVisible) {
                    toggleMenuItemVisibility(category, true);
                    toggleMenuItemVisibility(exportSubscriptions, true);
                    toggleMenuItemVisibility(search, true);
                }
            } else if (getSavedEntriesFragment().isAdded()) {
                toggleMenuItemVisibility(update, false);
                toggleMenuItemVisibility(filter, false);
                toggleMenuItemVisibility(category, false);
                toggleMenuItemVisibility(exportSubscriptions, false);

                if (!searchViewVisible) {
                    toggleMenuItemVisibility(sortEntries, true);
                    toggleMenuItemVisibility(search, true);
                    toggleMenuItemVisibility(exportSavedEntries, true);
                }

                final MenuItem itemSortOrderAsc = menu.findItem(R.id.action_sort_order_ascending);
                final MenuItem itemSortOrderDesc = menu.findItem(R.id.action_sort_order_descending);

                if (getSavedEntriesFragment().getSortOrder() == SavedEntriesFragment.SORT_ORDER_DESCENDING) {
                    itemSortOrderDesc.setEnabled(false);

                    if (!itemSortOrderAsc.isVisible()) {
                        itemSortOrderAsc.setVisible(true);
                    }
                } else {
                    itemSortOrderAsc.setEnabled(false);

                    if (!itemSortOrderDesc.isVisible()) {
                        itemSortOrderDesc.setVisible(true);
                    }
                }
            }

            if (!searchViewVisible) {
                toggleMenuItemVisibility(settings, true);
            }
        }

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_search:
            searchViewShow();
            return true;
        case R.id.action_settings:
            final Intent intent = new Intent(this, SettingsActivity.class);
            startActivityForResult(intent, REQUEST_CODE_SETTINGS);
            return true;
        case android.R.id.home:
            onBackPressed();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public Loader onCreateLoader(final int id, final Bundle args) {
        switch (id) {
        case IsFeedUpdateAvailableLoader.ID:
            return new IsFeedUpdateAvailableLoader(this);
        case ImportSubscriptionsLoader.ID:
            final Uri uri = Uri.parse(args.getString(KEY_IMPORT_SUBSCRIPTIONS));
            return new ImportSubscriptionsLoader(this, uri);
        case SavedEntriesSaveLoader.ID:
            final List<String> urls = args.getStringArrayList(KEY_ENTRY_URLS);
            final List<String> titles = args.getStringArrayList(KEY_ENTRY_TITLES);
            return new SavedEntriesSaveLoader(this, urls, titles);
        default:
            return null;
        }
    }

    @Override
    public void onLoadFinished(final Loader loader, final Object data) {
        final int id = loader.getId();

        switch (id) {
        case IsFeedUpdateAvailableLoader.ID:
            onFeedUpdateResult((String) data);
            break;
        case ImportSubscriptionsLoader.ID:
            onSubscriptionImportResult((List) data);
            break;
        case SavedEntriesSaveLoader.ID:
            showSnackbar(getString(R.string.saved_entries_save_succeeded));
            break;
        default:
            break;
        }

        getLoaderManager().destroyLoader(id);
    }

    @Override
    public void onLoaderReset(final Loader loader) {
    }

    private void onFeedUpdateResult(final String id) {
        getCurrentFeedFragment().currentFeedUpdateCheckFinished();

        final int errno = ErrorHandler.getErrno();

        if (errno < 0) {
            showSnackbar(ErrorHandler.resolveErrorMessage(this, errno));
        } else {
            final int position = SharedPrefUtils.getCurrentFeedPosition(this);
            SharedPrefUtils.updateSubscriptionIdAt(this, id, position);

            getCurrentFeedFragment().scrollToTop();
        }
    }

    private void onSubscriptionImportResult(final List outlines) {
        final int errno = ErrorHandler.getErrno();
        final boolean isNotInInitialSetup = isNotInInitialSetup();

        if (errno < 0) {
            if (isNotInInitialSetup) {
                showSnackbar(ErrorHandler.resolveErrorMessage(this, errno));
            }
        } else {
            SharedPrefUtils.addSubscriptions(this, outlines);

            if (isNotInInitialSetup) {
                showSnackbar(getString(R.string.subscription_import_succeeded));

                getFeedSubscriptionsFragment().feedSubscriptionsChanged();
            } else {
                removeFragment(getInitialSetupFragment(), true);

                mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_current_feed);
                mBottomNavigationView.setVisibility(View.VISIBLE);

                toggleActionBarVisibility(true);
                loadCurrentFeed(true);
            }
        }
    }

    private void addSubscription(final String url, final boolean coldLaunch) {
        if (isNotInInitialSetup()) {
            mBottomNavigationView.setSelectedItemId(R.id.action_feed_subscriptions);

            if (!coldLaunch && FeedSubscriptionFragment.getInstance().isAdded()) {
                FeedSubscriptionFragment.getInstance().dismiss();
            }
        } else {
            addFragment(getInitialSetupFragment(), false, false);
            mBottomNavigationView.setVisibility(View.GONE);
        }

        FeedSubscriptionFragment.getInstance(url).show(getFragmentManager(), FeedSubscriptionFragment.TAG);
    }

    public void addSubscription(final String title, final String category, final String url) {
        final int position = SharedPrefUtils.addSubscription(this, title, category, url);

        if (getFeedSubscriptionsFragment().isAdded()) {
            getFeedSubscriptionsFragment().feedSubscriptionsChanged(position);

            showSnackbar(getString(R.string.subscription_added));
        }

        if (getInitialSetupFragment().isAdded()) {
            removeFragment(getInitialSetupFragment(), false);

            mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_current_feed);
            mBottomNavigationView.setVisibility(View.VISIBLE);

            toggleActionBarVisibility(true);
            loadCurrentFeed(false);
        }
    }

    private void addFragment(final Fragment fragment, final boolean addToBackStack, final boolean allowStateLoss) {
        final FragmentManager fm = getFragmentManager();

        final FragmentTransaction transaction = fm.beginTransaction();

        final String tag;

        if (fragment instanceof CurrentFeedFragment) {
            tag = CurrentFeedFragment.TAG;
        } else if (fragment instanceof FeedSubscriptionsFragment) {
            tag = FeedSubscriptionsFragment.TAG;
        } else if (fragment instanceof SavedEntriesFragment) {
            tag = SavedEntriesFragment.TAG;
        } else if (fragment instanceof InitialSetupFragment) {
            tag = InitialSetupFragment.TAG;
        } else {
            tag = LoadCurrentFeedFragment.TAG;
        }

        transaction.add(R.id.ActivityMainFragmentContainer, fragment, tag);

        if (addToBackStack) {
            transaction.addToBackStack(tag);
        }

        if (allowStateLoss) {
            transaction.commitAllowingStateLoss();
        } else {
            transaction.commit();
        }
        fm.executePendingTransactions();
    }

    private void alterMenuItemAlpha(final MenuItem item, final boolean enable) {
        if (enable) {
            if (!item.isEnabled()) {
                item.setEnabled(true);
                item.getIcon().setAlpha(ICON_ALPHA_NORMAL);
            }
        } else if (item.isEnabled()) {
            item.setEnabled(false);
            item.getIcon().setAlpha(ICON_ALPHA_LOW);
        }
    }

    public void currentFeedLoaded() {
        if (getLoadCurrentFeedFragment().isAdded()) {
            removeFragment(getLoadCurrentFeedFragment(), true);
            addFragment(getCurrentFeedFragment(), true, true);
        }

        final List<SyndEntry> entries = CurrentFeed.getEntries();

        if (!entries.isEmpty()) {
            final int position = SharedPrefUtils.getCurrentFeedPosition(this);
            SharedPrefUtils.updateSubscriptionIdAt(this, entries.get(0).getUri(), position);
        }
    }

    public void editSubscription(final String category, final String title, final int position) {
        SharedPrefUtils.updateSubscriptionCategoryTitleAt(this, category, title, position);

        getFeedSubscriptionsFragment().feedSubscriptionsChanged();

        showSnackbar(getString(R.string.subscription_edit_succeeded));
    }

    @SuppressWarnings("SameParameterValue")
    private void exportSavedEntries(final Uri uri, final String mimeType) {
        if (mimeType.equals(MIME_TYPE_JSON)) {
            ExportUtils.exportSavedEntriesAsJSON(this, uri);
        }
    }

    private void exportSubscriptions(final Uri uri) {
        ExportUtils.exportSubscriptions(this, uri, mRetainCategories);

        final int errno = ErrorHandler.getErrno();

        if (errno < 0) {
            showSnackbar(ErrorHandler.resolveErrorMessage(this, ErrorHandler.getErrno()));
        } else {
            showSnackbar(getString(R.string.subscription_export_succeeded));
        }
    }

    private String getActionModeQuantityString(final int quantity) {
        final Resources res = getResources();

        if (getCurrentFeedFragment().isAdded()) {
            return res.getQuantityString(R.plurals.action_mode_current_feed, quantity);
        } else if (getFeedSubscriptionsFragment().isAdded()) {
            return res.getQuantityString(R.plurals.action_mode_feed_subscriptions, quantity);
        }

        return res.getQuantityString(R.plurals.action_mode_saved_entries, quantity);
    }

    public HistoryAwareBottomNavigationView getBottomNavigationView() {
        return mBottomNavigationView;
    }

    private CurrentFeedFragment getCurrentFeedFragment() {
        if (mCurrentFeedFragment == null) {
            final Fragment fragment = getFragmentManager().findFragmentByTag(CurrentFeedFragment.TAG);

            if (fragment != null) {
                mCurrentFeedFragment = (CurrentFeedFragment) fragment;
            } else {
                mCurrentFeedFragment = new CurrentFeedFragment();
            }
        }

        return mCurrentFeedFragment;
    }

    private FeedSubscriptionsFragment getFeedSubscriptionsFragment() {
        if (mFeedSubscriptionsFragment == null) {
            final Fragment fragment = getFragmentManager().findFragmentByTag(FeedSubscriptionsFragment.TAG);

            if (fragment != null) {
                mFeedSubscriptionsFragment = (FeedSubscriptionsFragment) fragment;
            } else {
                mFeedSubscriptionsFragment = new FeedSubscriptionsFragment();
            }
        }

        return mFeedSubscriptionsFragment;
    }

    private InitialSetupFragment getInitialSetupFragment() {
        if (mInitialSetupFragment == null) {
            final Fragment fragment = getFragmentManager().findFragmentByTag(InitialSetupFragment.TAG);

            if (fragment != null) {
                mInitialSetupFragment = (InitialSetupFragment) fragment;
            } else {
                mInitialSetupFragment = new InitialSetupFragment();
            }
        }

        return mInitialSetupFragment;
    }

    private LoadCurrentFeedFragment getLoadCurrentFeedFragment() {
        if (mLoadCurrentFeedFragment == null) {
            final Fragment fragment = getFragmentManager().findFragmentByTag(LoadCurrentFeedFragment.TAG);

            if (fragment != null) {
                mLoadCurrentFeedFragment = (LoadCurrentFeedFragment) fragment;
            } else {
                mLoadCurrentFeedFragment = new LoadCurrentFeedFragment();
            }
        }

        return mLoadCurrentFeedFragment;
    }

    public SavedEntriesFragment getSavedEntriesFragment() {
        if (mSavedEntriesFragment == null) {
            final Fragment fragment = getFragmentManager().findFragmentByTag(SavedEntriesFragment.TAG);

            if (fragment != null) {
                mSavedEntriesFragment = (SavedEntriesFragment) fragment;
            } else {
                mSavedEntriesFragment = new SavedEntriesFragment();
            }
        }

        return mSavedEntriesFragment;
    }

    private void importSubscriptions(final Uri uri) {
        final Bundle args = new Bundle();
        args.putString(KEY_IMPORT_SUBSCRIPTIONS, uri.toString());

        getLoaderManager().restartLoader(ImportSubscriptionsLoader.ID, args, this);
    }

    public boolean isCategoriesFilterNotApplied() {
        return !mIsCategoriesFilterApplied;
    }

    private boolean isNotInInitialSetup() {
        return !TextUtils.isEmpty(SharedPrefUtils.getCurrentFeedUrl(this));
    }

    public boolean isRecyclerViewItemSelected(final int position) {
        return mSelectedRecyclerViewPositions != null && mSelectedRecyclerViewPositions.contains(position);
    }

    private void loadCurrentFeed(final boolean allowStateLoss) {
        if (getFeedSubscriptionsFragment().isAdded()) {
            replaceFragment(getLoadCurrentFeedFragment(), true);
        }

        addFragment(getLoadCurrentFeedFragment(), false, allowStateLoss);
    }

    private void loadCurrentFeedOrShowInitialSetup() {
        if (isNotInInitialSetup()) {
            loadCurrentFeed(false);
        } else {
            mBottomNavigationView.setVisibility(View.GONE);
            addFragment(getInitialSetupFragment(), false, false);
        }
    }

    private boolean loadNewCurrentFeed() {
        if (mLoadNewCurrentFeed) {
            mLoadNewCurrentFeed = false;

            return true;
        }

        return false;
    }

    private boolean navigateBackInFragmentBackStack() {
        final FragmentManager fm = getFragmentManager();

        fm.popBackStackImmediate();

        if (fm.getBackStackEntryCount() <= 0) {
            return false;
        }

        if (mNavigateBackNewCurrentFeed) {
            fm.popBackStackImmediate();

            getLoadCurrentFeedFragment().cancelFeedLoading();

            SharedPrefUtils.putCurrentFeedPosition(this, SharedPrefUtils.getPreviousFeedPosition(this));

            replaceFragment(getLoadCurrentFeedFragment(), false);

            mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_current_feed);
            mNavigateBackNewCurrentFeed = false;
        } else {
            final String tag = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1).getName();

            if (tag.equals(CurrentFeedFragment.TAG)) {
                mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_current_feed);
            } else if (tag.equals(FeedSubscriptionsFragment.TAG)) {
                mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_feed_subscriptions);
            } else {
                fm.popBackStackImmediate();

                mBottomNavigationView.setSelectedItemIdNoAction(R.id.action_feed_subscriptions);
                mNavigateBackNewCurrentFeed = true;
            }
        }

        return true;
    }

    private void recyclerViewScrollTo(final int position, final List<Integer> highlight) {
        if (getCurrentFeedFragment().isAdded()) {
            if (highlight != null) {
                getCurrentFeedFragment().highlightVisibleSearchResults(highlight);
            }
            getCurrentFeedFragment().scrollTo(position);
        } else if (getFeedSubscriptionsFragment().isAdded()) {
            if (highlight != null) {
                getFeedSubscriptionsFragment().highlightVisibleSearchResults(highlight);
            }
            getFeedSubscriptionsFragment().scrollTo(position);
        } else {
            if (highlight != null) {
                getSavedEntriesFragment().highlightVisibleSearchResults(highlight);
            }
            getSavedEntriesFragment().scrollTo(position);
        }
    }

    private void removeFragment(final Fragment fragment, final boolean allowStateLoss) {
        final FragmentManager fm = getFragmentManager();
        final FragmentTransaction transaction = fm.beginTransaction();

        transaction.remove(fragment);

        if (allowStateLoss) {
            transaction.commitAllowingStateLoss();
        } else {
            transaction.commit();
        }
        fm.executePendingTransactions();
    }

    private void replaceFragment(final Fragment fragment, final boolean addToBackStack) {
        final FragmentManager fm = getFragmentManager();
        final FragmentTransaction transaction = fm.beginTransaction();

        final String tag;

        if (fragment instanceof CurrentFeedFragment) {
            tag = CurrentFeedFragment.TAG;
        } else if (fragment instanceof FeedSubscriptionsFragment) {
            tag = FeedSubscriptionsFragment.TAG;
        } else if (fragment instanceof SavedEntriesFragment) {
            tag = SavedEntriesFragment.TAG;
        } else if (fragment instanceof InitialSetupFragment) {
            tag = InitialSetupFragment.TAG;
        } else {
            tag = LoadCurrentFeedFragment.TAG;
        }

        transaction.replace(R.id.ActivityMainFragmentContainer, fragment, tag);

        if (addToBackStack) {
            transaction.addToBackStack(tag);
        }

        transaction.commit();
        fm.executePendingTransactions();
    }

    private <T> void resetCardViewBackground(final T positions, final Class<T> clazz) {
        if (getCurrentFeedFragment().isAdded()) {
            getCurrentFeedFragment().resetCardViewBackground(positions, clazz);
        } else if (getFeedSubscriptionsFragment().isAdded()) {
            getFeedSubscriptionsFragment().resetCardViewBackground(positions, clazz);
        } else {
            getSavedEntriesFragment().resetCardViewBackground(positions, clazz);
        }
    }

    private void saveEntries() {
        if (!TextUtils.isEmpty(SharedPrefUtils.get(MainActivity.this, KEY_HASHED_PASSWORD, String.class))) {
            final int size = mSelectedRecyclerViewPositions.size();

            final ArrayList<String> entryUrls = new ArrayList<>(size);
            final ArrayList<String> entryTitles = new ArrayList<>(size);

            final List<SyndEntry> entries = CurrentFeed.getEntries();

            for (final Integer position : mSelectedRecyclerViewPositions) {
                final SyndEntry entry = entries.get(position);

                entryUrls.add(entry.getLink());
                entryTitles.add(entry.getTitle());
            }

            SavedEntriesSavePasswordFragment.getInstance(entryUrls, entryTitles).show(getFragmentManager(),
                    SavedEntriesSavePasswordFragment.TAG);
        } else {
            showSnackbar(getString(R.string.saved_entries_setup_password));
        }
    }

    @SuppressWarnings("ConstantConditions")
    private void setActionBarColor(@ColorRes final int colorRes) {
        getSupportActionBar().setBackgroundDrawable(new ColorDrawable(getColor(colorRes)));
    }

    private void setStatusBarColor(@ColorRes final int colorRes) {
        getWindow().setStatusBarColor(getColor(colorRes));
    }

    public void showFeedSubscriptionBaseFragment() {
        if (isNotInInitialSetup()) {
            FeedSubscriptionBaseFragment.getInstance().show(getSupportFragmentManager(),
                    FeedSubscriptionBaseFragment.TAG);
        }
    }

    private void showSnackbar(final String msg) {
        if (getCurrentFeedFragment().isAdded()) {
            SnackbarUtils.show(this, getCurrentFeedFragment().getLayout(), msg);
        } else if (getFeedSubscriptionsFragment().isAdded()) {
            SnackbarUtils.show(this, getFeedSubscriptionsFragment().getLayout(), msg);
        } else {
            SnackbarUtils.show(this, getSavedEntriesFragment().getLayout(), msg);
        }
    }

    public void showSubscriptionAt(final int position) {
        if (mFeedSubscriptionsChanged || SharedPrefUtils.getCurrentFeedPosition(this) != position) {
            updateCurrentFeedPosition(position);
        }

        mBottomNavigationView.setSelectedItemId(R.id.action_current_feed);
        invalidateOptionsMenu();
    }

    @SuppressWarnings("SameParameterValue")
    public void startActivity(final String action, final String mimeType, final boolean... retainCategories) {
        final Intent intent = new Intent(action).setType(mimeType);

        if (action.equals(Intent.ACTION_OPEN_DOCUMENT)) {
            startActivityForResult(intent, REQUEST_CODE_IMPORT_SUBSCRIPTIONS);
        } else if (action.equals(Intent.ACTION_CREATE_DOCUMENT)) {
            final String title = TAG.toLowerCase() + "_" + new LocalDateTime().toString();

            if (mimeType.equals(MIME_TYPE_OPML)) {
                if (retainCategories.length > 0) {
                    mRetainCategories = retainCategories[0];
                }
                intent.putExtra(Intent.EXTRA_TITLE, title);
                startActivityForResult(intent, REQUEST_CODE_EXPORT_SUBSCRIPTIONS);
            } else if (mimeType.equals(MIME_TYPE_JSON)) {
                intent.putExtra(Intent.EXTRA_TITLE, title + ".json");
                startActivityForResult(intent, REQUEST_CODE_EXPORT_SAVED_ENTRIES);
            }
        }
    }

    @SuppressWarnings("ConstantConditions")
    private void toggleActionBarVisibility(final boolean visible) {
        final ActionBar actionBar = getSupportActionBar();

        if (visible) {
            if (!actionBar.isShowing()) {
                actionBar.show();
            }
        } else if (actionBar.isShowing()) {
            actionBar.hide();
        }
    }

    private void toggleMenuItemVisibility(final MenuItem item, final boolean visible) {
        if (visible) {
            if (!item.isVisible()) {
                item.setVisible(true);
            }
        } else if (item.isVisible()) {
            item.setVisible(false);
        }
    }

    private void toggleSystemUiVisibility(final boolean reset) {
        final View view = getWindow().getDecorView();

        if (reset) {
            view.setSystemUiVisibility(0);
        } else {
            view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        }
    }

    public void unsubscribe(final List<String> titles) {
        mActionMode.finish();

        if (SharedPrefUtils.unsubscribe(this, titles)) {
            updateCurrentFeedPosition(0);

            getFeedSubscriptionsFragment().feedSubscriptionsChanged();

            mFeedSubscriptionsChanged = true;
        }

        if (SharedPrefUtils.isSubscriptionsEmpty(this)) {
            getLoadCurrentFeedFragment().cancelFeedLoading();

            final Loader loader = getLoaderManager().getLoader(IsFeedUpdateAvailableLoader.ID);

            if (loader != null && loader.isStarted()) {
                loader.cancelLoad();
            }

            CurrentFeed.set(null);

            removeFragment(getFeedSubscriptionsFragment(), false);

            toggleActionBarVisibility(false);

            getFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

            mCurrentFeedFragment = null;
            mFeedSubscriptionsFragment = null;
            mSavedEntriesFragment = null;
            mInitialSetupFragment = null;
            mLoadCurrentFeedFragment = null;

            mBottomNavigationView.setVisibility(View.GONE);

            replaceFragment(getInitialSetupFragment(), false);
        }
    }

    private void updateActionModeTitles(final String element) {
        if (mActionMode != null) {
            final StringBuilder subtitle = new StringBuilder();

            final int size = mSelectedRecyclerViewPositions.size();

            for (int i = 0; i < size; i++) {
                final Integer position = mSelectedRecyclerViewPositions.get(i);
                final String title;

                if (getCurrentFeedFragment().isAdded()) {
                    title = CurrentFeed.getTitleForEntry(CurrentFeed.getEntries().get(position));
                } else if (getFeedSubscriptionsFragment().isAdded()) {
                    title = SharedPrefUtils.getSubscriptionTitleAt(this, position);
                } else {
                    title = SavedEntries.getSavedEntryTitleAt(position);
                }

                if (i > 0) {
                    subtitle.append(", ");
                    subtitle.append(title);
                } else {
                    subtitle.append(title);
                }
            }

            mActionMode.setTitle(String.valueOf(mSelectedRecyclerViewPositions.size()) + ' ' + element + ' '
                    + getString(R.string.selected));
            mActionMode.setSubtitle(subtitle.toString());
        }
    }

    private void updateCurrentFeedPosition(final int position) {
        getLoadCurrentFeedFragment().cancelFeedLoading();

        SharedPrefUtils.putCurrentFeedPosition(this, position);

        mFeedSubscriptionsChanged = false;
        mLoadNewCurrentFeed = true;
    }

    @SuppressWarnings("ConstantConditions")
    public boolean searchViewIsVisible() {
        return TextUtils.isEmpty(getSupportActionBar().getTitle());
    }

    private String searchViewGetQuery() {
        return mSearchEditText.getText().toString();
    }

    public SearchResults searchViewGetSearchResultsCursor() {
        return mSearchResults;
    }

    private void searchViewNavigateCursor(final boolean next) {
        if (mSearchResults != null && !mSearchResults.isEmpty()) {
            final int previous = mSearchResults.current();

            if (next) {
                recyclerViewScrollTo(mSearchResults.next(), null);
            } else {
                recyclerViewScrollTo(mSearchResults.previous(), null);
            }

            final int current = mSearchResults.current();

            if (getCurrentFeedFragment().isAdded()) {
                getCurrentFeedFragment().updateHighlightedSearchResult(previous, current);
            } else if (getFeedSubscriptionsFragment().isAdded()) {
                getFeedSubscriptionsFragment().updateHighlightedSearchResult(previous, current);
            } else {
                getSavedEntriesFragment().updateHighlightedSearchResult(previous, current);
            }
        }
    }

    @SuppressWarnings("ConstantConditions")
    private void searchViewQueryTextChange(final CharSequence query, final ImageButton navigateBack,
            final TextView results) {
        @DrawableRes
        final int drawableRes;

        if (!TextUtils.isEmpty(query)) {
            if (ThemeUtils.isDarkThemeSelected(this)) {
                drawableRes = R.drawable.ic_clear_white_24dp;
            } else {
                drawableRes = R.drawable.ic_clear_black_24dp;
            }
        } else {
            if (results.getVisibility() != View.INVISIBLE) {
                results.setVisibility(View.INVISIBLE);
            }

            if (ThemeUtils.isDarkThemeSelected(this)) {
                drawableRes = R.drawable.ic_arrow_back_white_24dp;
            } else {
                drawableRes = R.drawable.ic_arrow_back_black_24dp;
            }
        }

        if (navigateBack.getDrawable().getConstantState() != getDrawable(drawableRes).getConstantState()) {
            navigateBack.setImageResource(drawableRes);
        }

        if (mSearchResults != null && !mSearchResults.isEmpty()) {
            resetCardViewBackground(mSearchResults.getAll(), List.class);
            mSearchResults = null;
        }
    }

    @SuppressWarnings("ConstantConditions")
    private void searchViewQueryTextSubmit(final TextView results) {
        final String query = searchViewGetQuery();

        if (TextUtils.isEmpty(query)) {
            return;
        }

        if (getCurrentFeedFragment().isAdded()) {
            mSearchResults = CurrentFeed.getSearchResultsFor(query,
                    getCurrentFeedFragment().getFirstCompletelyVisibleItemPosition());
        } else if (getFeedSubscriptionsFragment().isAdded()) {
            mSearchResults = SharedPrefUtils.getSearchResultsFor(MainActivity.this, query,
                    getFeedSubscriptionsFragment().getFirstCompletelyVisibleItemPosition());
        } else {
            mSearchResults = SavedEntries.getSearchResultsFor((query),
                    getSavedEntriesFragment().getFirstCompletelyVisibleItemPosition());
        }

        if (!mSearchResults.isEmpty()) {
            searchViewShowCursorPosition(results);
            recyclerViewScrollTo(mSearchResults.current(), mSearchResults.getAll());
        } else {
            showSnackbar(getString(R.string.no_search_results));
        }
    }

    @SuppressWarnings("ConstantConditions")
    private void searchViewHide() {
        final ActionBar actionBar = getSupportActionBar();
        final android.support.v7.widget.Toolbar toolbar = (android.support.v7.widget.Toolbar) actionBar
                .getCustomView().getParent();

        if (!TextUtils.isEmpty(searchViewGetQuery())) {
            mSearchEditText.setText(null);

            SoftInputUtils.forceShowSoftInput(this, mSearchEditText);
        } else {
            setActionBarColor(TypedValueUtils.resolve(this, R.attr.colorPrimary));
            setStatusBarColor(TypedValueUtils.resolve(this, R.attr.colorPrimaryDark));

            toggleSystemUiVisibility(true);

            toolbar.setContentInsetsAbsolute(mActionBarInsets[0], mActionBarInsets[1]);

            SoftInputUtils.dismissSoftInput(this, toolbar);

            actionBar.setCustomView(null);
            actionBar.setDisplayShowCustomEnabled(false);
            actionBar.setDisplayShowTitleEnabled(true);

            invalidateOptionsMenu();
        }
    }

    private void searchViewShowCursorPosition(final TextView results) {
        if (mSearchResults != null) {
            final String currentPosition = mSearchResults.toString();

            if (!TextUtils.isEmpty(currentPosition)) {
                results.setText(currentPosition);

                if (results.getVisibility() != View.VISIBLE) {
                    results.setVisibility(View.VISIBLE);
                }
            }
        }
    }

    @SuppressWarnings("ConstantConditions")
    private void searchViewShow(final String... query) {
        final ActionBar actionBar = getSupportActionBar();

        setActionBarColor(TypedValueUtils.resolve(this, R.attr.colorActionBarSearchViewExpanded));
        setStatusBarColor(TypedValueUtils.resolve(this, R.attr.colorStatusBarSearchViewExpanded));

        actionBar.setDisplayShowTitleEnabled(false);

        actionBar.setCustomView(R.layout.activity_main_search_view);
        actionBar.setDisplayShowCustomEnabled(true);

        invalidateOptionsMenu();

        final View view = actionBar.getCustomView();

        final android.support.v7.widget.Toolbar toolbar = (android.support.v7.widget.Toolbar) view.getParent();

        mActionBarInsets = new int[] { toolbar.getContentInsetLeft(), toolbar.getContentInsetRight() };

        toolbar.setContentInsetsAbsolute(0, 0);

        mSearchEditText = view.findViewById(R.id.ActivityMainSearchEditText);

        final TextView results = view.findViewById(R.id.ActivityMainResultsTextView);
        final ImageButton navigateBack = view.findViewById(R.id.ActivityMainBackImageButton);
        final ImageButton previous = view.findViewById(R.id.ActivityMainSearchPreviousImageButton);
        final ImageButton next = view.findViewById(R.id.ActivityMainSearchNextImageButton);

        results.setVisibility(View.INVISIBLE);

        if (ThemeUtils.isDarkThemeSelected(this)) {
            navigateBack.setImageDrawable(getDrawable(R.drawable.ic_arrow_back_white_24dp));
            previous.setImageDrawable(getDrawable(R.drawable.ic_navigate_before_white_24dp));
            next.setImageDrawable(getDrawable(R.drawable.ic_navigate_next_white_24dp));
        } else {
            toggleSystemUiVisibility(false);
        }

        mSearchEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(final CharSequence query, final int i, final int i1, final int i2) {
            }

            @Override
            public void onTextChanged(final CharSequence query, final int i, final int i1, final int i2) {
                searchViewQueryTextChange(query, navigateBack, results);
            }

            @Override
            public void afterTextChanged(final Editable editable) {
            }
        });

        mSearchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(final TextView textView, final int id, final KeyEvent keyEvent) {
                if (id == EditorInfo.IME_ACTION_SEARCH) {
                    SoftInputUtils.dismissSoftInput(MainActivity.this, mSearchEditText);

                    searchViewQueryTextSubmit(results);
                }

                return results.getVisibility() != View.INVISIBLE;
            }
        });

        navigateBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View view) {
                searchViewHide();
            }
        });

        previous.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View view) {
                searchViewNavigateCursor(false);
                searchViewShowCursorPosition(results);
            }
        });

        next.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View view) {
                searchViewNavigateCursor(true);
                searchViewShowCursorPosition(results);
            }
        });

        if (query.length > 0) {
            mSearchEditText.setText(query[0]);
        }

        SoftInputUtils.forceShowSoftInput(this, mSearchEditText);
    }

    public void startOrUpdateActionMode(final int position) {
        final boolean isCurrentFeedSelected = getCurrentFeedFragment().isAdded();
        final boolean isFeedSubscriptionsSelected = getFeedSubscriptionsFragment().isAdded();

        if (mActionMode != null) {
            if (!mSelectedRecyclerViewPositions.contains(position)) {
                mSelectedRecyclerViewPositions.add(position);

                updateActionModeTitles(getActionModeQuantityString(mSelectedRecyclerViewPositions.size()));
            } else {
                mSelectedRecyclerViewPositions.remove(Integer.valueOf(position));

                if (mSelectedRecyclerViewPositions.isEmpty()) {
                    resetCardViewBackground(position, Integer.class);
                    mActionMode.finish();
                } else {
                    updateActionModeTitles(getActionModeQuantityString(mSelectedRecyclerViewPositions.size()));
                }

                resetCardViewBackground(position, Integer.class);
            }
            return;
        }

        mSelectedRecyclerViewPositions = new ArrayList<>(Collections.singletonList(position));

        mActionMode = startActionMode(new android.view.ActionMode.Callback() {
            @Override
            public boolean onCreateActionMode(final android.view.ActionMode mode, final Menu menu) {
                mode.getMenuInflater().inflate(R.menu.activity_main_action_mode, menu);

                setStatusBarColor(TypedValueUtils.resolve(MainActivity.this, R.attr.colorStatusBarActionMode));

                final int size = mSelectedRecyclerViewPositions.size();

                mode.setTitle(String.valueOf(size) + ' ' + getActionModeQuantityString(size) + ' '
                        + getString(R.string.selected));

                final StringBuilder subtitle = new StringBuilder();

                if (isCurrentFeedSelected) {
                    subtitle.append(CurrentFeed.getTitleForEntry(CurrentFeed.getEntries().get(position)));
                } else if (isFeedSubscriptionsSelected) {
                    subtitle.append(SharedPrefUtils.getSubscriptionTitleAt(MainActivity.this, position));
                } else {
                    subtitle.append(SavedEntries.getSavedEntryTitleAt(position));
                }

                if (mSelectedRecyclerViewPositions.size() > 1) {
                    subtitle.append(",\u2026");
                }

                mode.setSubtitle(subtitle.toString());

                return true;
            }

            @Override
            public boolean onPrepareActionMode(final android.view.ActionMode mode, final Menu menu) {
                final MenuItem readEntry = menu.findItem(R.id.action_read_entry);
                final MenuItem readComments = menu.findItem(R.id.action_read_comments);
                final MenuItem saveEntries = menu.findItem(R.id.action_save_entries);

                if (isCurrentFeedSelected) {
                    final SyndEntry entry = CurrentFeed.getEntries().get(position);

                    if (mSelectedRecyclerViewPositions.size() > 1) {
                        readEntry.setVisible(false);
                        readComments.setVisible(false);

                        if (TextUtils.isEmpty(CurrentFeed.getLinkForEntry(entry))) {
                            saveEntries.setVisible(false);
                        }
                    } else {
                        if (!TextUtils.isEmpty(CurrentFeed.getLinkForEntry(entry))) {
                            readEntry.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
                            readEntry.setVisible(true);
                        } else {
                            readEntry.setVisible(false);
                        }

                        if (!TextUtils.isEmpty(CurrentFeed.getCommentsForEntry(entry))) {
                            readComments.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
                            readComments.setVisible(true);
                        } else {
                            readComments.setVisible(false);
                        }

                        saveEntries.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
                    }
                } else if (isFeedSubscriptionsSelected) {
                    final MenuItem itemUnsubscribeFromFeeds = menu.findItem(R.id.action_unsubscribe_from_feeds);
                    final MenuItem itemEditSubscription = menu.findItem(R.id.action_edit_subscription);

                    readEntry.setVisible(false);
                    readComments.setVisible(false);
                    saveEntries.setVisible(false);

                    itemUnsubscribeFromFeeds.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
                    itemUnsubscribeFromFeeds.setVisible(true);

                    if (mSelectedRecyclerViewPositions.size() > 1) {
                        itemEditSubscription.setVisible(false);
                    } else {
                        itemEditSubscription.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
                        itemEditSubscription.setVisible(true);
                    }
                } else {
                    final MenuItem itemDeleteSavedEntries = menu.findItem(R.id.action_delete_entries);

                    readComments.setVisible(false);
                    saveEntries.setVisible(false);

                    itemDeleteSavedEntries.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);

                    itemDeleteSavedEntries.setVisible(true);

                    if (mSelectedRecyclerViewPositions.size() > 1) {
                        readEntry.setVisible(false);
                    } else {
                        readEntry.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
                        if (!readEntry.isVisible()) {
                            readEntry.setVisible(true);
                        }
                    }
                }

                return true;
            }

            @Override
            public boolean onActionItemClicked(final android.view.ActionMode mode, final MenuItem item) {
                switch (item.getItemId()) {
                case R.id.action_read_entry:
                    final String link;
                    if (isCurrentFeedSelected) {
                        link = CurrentFeed.getLinkForEntry(CurrentFeed.getEntries().get(position));
                    } else {
                        link = SavedEntries.getSavedEntryUrlAt(mSelectedRecyclerViewPositions.get(0));
                    }
                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link)));
                    mode.finish();

                    return true;
                case R.id.action_read_comments:
                    mode.finish();
                    startActivity(new Intent(Intent.ACTION_VIEW,
                            Uri.parse(CurrentFeed.getCommentsForEntry(CurrentFeed.getEntries().get(position)))));

                    return true;
                case R.id.action_save_entries:
                    saveEntries();
                    mode.finish();

                    return true;
                case R.id.action_unsubscribe_from_feeds:
                    final List<String> feedUnsubscriptions = SharedPrefUtils
                            .getSubscriptionTitlesFor(MainActivity.this, mSelectedRecyclerViewPositions);

                    UnsubscribeFromFeedsFragment.getInstance((ArrayList<String>) feedUnsubscriptions)
                            .show(getFragmentManager(), UnsubscribeFromFeedsFragment.TAG);

                    return true;
                case R.id.action_delete_entries:
                    SavedEntriesDeleteEntriesFragment.getInstance(mSelectedRecyclerViewPositions)
                            .show(getFragmentManager(), SavedEntriesDeleteEntriesFragment.TAG);

                    mode.finish();

                    return true;
                case R.id.action_edit_subscription:
                    FeedSubscriptionEditFragment.getInstance(position).show(getFragmentManager(),
                            FeedSubscriptionEditFragment.TAG);

                    mode.finish();

                    return true;
                default:
                    return false;
                }
            }

            @Override
            public void onDestroyActionMode(final android.view.ActionMode mode) {
                setStatusBarColor(TypedValueUtils.resolve(MainActivity.this, R.attr.colorPrimaryDark));

                resetCardViewBackground(mSelectedRecyclerViewPositions, List.class);

                mSelectedRecyclerViewPositions = null;
                mActionMode = null;
            }
        });
    }

    public void startActionMode(final List<Integer> positions) {
        if (mActionMode != null) {
            return;
        }

        mIsCategoriesFilterApplied = true;
        mSelectedRecyclerViewPositions = positions;

        mActionMode = startActionMode(new android.view.ActionMode.Callback() {
            private int mCursor;

            @Override
            public boolean onCreateActionMode(final android.view.ActionMode mode, final Menu menu) {
                mode.getMenuInflater().inflate(R.menu.activity_main_action_mode_filter, menu);

                final MenuItem previous = menu.findItem(R.id.action_filter_previous);
                final MenuItem next = menu.findItem(R.id.action_filter_next);

                setStatusBarColor(TypedValueUtils.resolve(MainActivity.this, R.attr.colorStatusBarActionMode));

                if (ThemeUtils.isDarkThemeSelected(MainActivity.this)) {
                    previous.setIcon(getDrawable(R.drawable.ic_arrow_upward_white_24dp));
                    next.setIcon(getDrawable(R.drawable.ic_arrow_downward_white_24dp));
                }

                final CurrentFeedFragment fragment = getCurrentFeedFragment();

                fragment.highlightVisibleSearchResults(positions);
                fragment.scrollTo(positions.get(mCursor));

                return true;
            }

            @Override
            public boolean onPrepareActionMode(final android.view.ActionMode mode, final Menu menu) {
                final MenuItem previous = menu.findItem(R.id.action_filter_previous);
                final MenuItem next = menu.findItem(R.id.action_filter_next);
                final MenuItem skipToStart = menu.findItem(R.id.action_filter_skip_to_start);
                final MenuItem skipToEnd = menu.findItem(R.id.action_filter_skip_to_end);

                final int size = positions.size();

                if (size == 1) {
                    alterMenuItemAlpha(previous, false);
                    alterMenuItemAlpha(next, false);
                    alterMenuItemAlpha(skipToStart, false);
                    alterMenuItemAlpha(skipToEnd, false);
                } else if (mCursor == 0) {
                    alterMenuItemAlpha(previous, false);
                    alterMenuItemAlpha(skipToStart, false);

                    if (!next.isEnabled()) {
                        alterMenuItemAlpha(next, true);
                        alterMenuItemAlpha(skipToEnd, true);
                    }
                } else if (mCursor == size - 1) {
                    alterMenuItemAlpha(next, false);
                    alterMenuItemAlpha(skipToEnd, false);

                    if (!previous.isEnabled()) {
                        alterMenuItemAlpha(previous, true);
                        alterMenuItemAlpha(skipToStart, true);
                    }
                } else if (!previous.isEnabled()) {
                    alterMenuItemAlpha(previous, true);
                    alterMenuItemAlpha(skipToStart, true);
                } else if (!next.isEnabled()) {
                    alterMenuItemAlpha(next, true);
                    alterMenuItemAlpha(skipToEnd, true);
                }

                mode.setTitle(String.valueOf(mCursor + 1) + ' ' + getString(R.string.of) + ' ' + size);
                mode.setSubtitle(
                        CurrentFeed.getTitleForEntry(CurrentFeed.getEntries().get(positions.get(mCursor) - 1)));

                return true;
            }

            @Override
            public boolean onActionItemClicked(final android.view.ActionMode mode, final MenuItem item) {
                switch (item.getItemId()) {
                case R.id.action_filter_next:
                    mCursor++;
                    getCurrentFeedFragment().scrollTo(positions.get(mCursor));
                    mode.invalidate();

                    return true;
                case R.id.action_filter_previous:
                    mCursor--;
                    getCurrentFeedFragment().scrollTo(positions.get(mCursor));
                    mode.invalidate();

                    return true;
                case R.id.action_filter_skip_to_start:
                    mCursor = 0;
                    getCurrentFeedFragment().scrollTo(positions.get(mCursor));
                    mode.invalidate();

                    return true;
                case R.id.action_filter_skip_to_end:
                    mCursor = positions.size() - 1;
                    getCurrentFeedFragment().scrollTo(positions.get(mCursor));
                    mode.invalidate();

                    return true;
                default:
                    return false;
                }
            }

            @Override
            public void onDestroyActionMode(final android.view.ActionMode mode) {
                setStatusBarColor(TypedValueUtils.resolve(MainActivity.this, R.attr.colorPrimaryDark));

                resetCardViewBackground(positions, List.class);

                final Menu menu = mode.getMenu();

                menu.findItem(R.id.action_filter_next).getIcon().setAlpha(ICON_ALPHA_NORMAL);
                menu.findItem(R.id.action_filter_previous).getIcon().setAlpha(ICON_ALPHA_NORMAL);
                menu.findItem(R.id.action_filter_skip_to_end).getIcon().setAlpha(ICON_ALPHA_NORMAL);
                menu.findItem(R.id.action_filter_skip_to_start).getIcon().setAlpha(ICON_ALPHA_NORMAL);

                mIsCategoriesFilterApplied = false;
                mSelectedRecyclerViewPositions = null;
                mActionMode = null;
            }
        });
    }
}