package com.fekracomputers.islamiclibrary.browsing.activity;


import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.graphics.drawable.DrawerArrowDrawable;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.SwitchCompat;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import com.fekracomputers.islamiclibrary.R;
import com.fekracomputers.islamiclibrary.appliation.IslamicLibraryApplication;
import com.fekracomputers.islamiclibrary.browsing.dialog.ConfirmBatchDownloadDialogFragment;
import com.fekracomputers.islamiclibrary.browsing.dialog.ConfirmBookDeleteDialogFragment;
import com.fekracomputers.islamiclibrary.browsing.fragment.AuthorListFragment;
import com.fekracomputers.islamiclibrary.browsing.fragment.BookCategoryFragment;
import com.fekracomputers.islamiclibrary.browsing.fragment.BookInformationFragment;
import com.fekracomputers.islamiclibrary.browsing.fragment.BookListFragment;
import com.fekracomputers.islamiclibrary.browsing.fragment.LibraryFragment;
import com.fekracomputers.islamiclibrary.browsing.interfaces.BookCardEventListener;
import com.fekracomputers.islamiclibrary.browsing.interfaces.BookCardEventsCallback;
import com.fekracomputers.islamiclibrary.browsing.interfaces.BrowsingActivityListingFragment;
import com.fekracomputers.islamiclibrary.databases.BooksInformationDBContract;
import com.fekracomputers.islamiclibrary.databases.BooksInformationDbHelper;
import com.fekracomputers.islamiclibrary.databases.UserDataDBHelper;
import com.fekracomputers.islamiclibrary.download.downloader.BooksDownloader;
import com.fekracomputers.islamiclibrary.download.model.DownloadsConstants;
import com.fekracomputers.islamiclibrary.download.service.RefreshBooksWithDirectoryService;
import com.fekracomputers.islamiclibrary.download.view.DownloadProgressActivity;
import com.fekracomputers.islamiclibrary.homeScreen.callbacks.BookCollectionsCallBack;
import com.fekracomputers.islamiclibrary.homeScreen.controller.BookCollectionsController;
import com.fekracomputers.islamiclibrary.homeScreen.dialog.RenameCollectionDialogFragment;
import com.fekracomputers.islamiclibrary.model.AuthorInfo;
import com.fekracomputers.islamiclibrary.model.BookCategory;
import com.fekracomputers.islamiclibrary.model.BooksCollection;
import com.fekracomputers.islamiclibrary.reminder.AppRateController;
import com.fekracomputers.islamiclibrary.reminder.DonationReminderDialogFragment;
import com.fekracomputers.islamiclibrary.search.view.SearchRequestPopupFragment;
import com.fekracomputers.islamiclibrary.search.view.SearchResultActivity;
import com.fekracomputers.islamiclibrary.search.view.SearchResultFragment;
import com.fekracomputers.islamiclibrary.settings.AboutActivity;
import com.fekracomputers.islamiclibrary.settings.AboutUtil;
import com.fekracomputers.islamiclibrary.settings.HelpActivity;
import com.fekracomputers.islamiclibrary.settings.SettingsActivity;
import com.fekracomputers.islamiclibrary.userNotes.GlobalUserNotesFragment;
import com.fekracomputers.islamiclibrary.utility.Util;
import com.google.gson.Gson;
import com.polyak.iconswitch.IconSwitch;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import static com.fekracomputers.islamiclibrary.homeScreen.dialog.RenameCollectionDialogFragment.KEY_COLLECTION_GSON;
import static com.fekracomputers.islamiclibrary.homeScreen.dialog.RenameCollectionDialogFragment.KEY_OLD_NAME;
import static com.fekracomputers.islamiclibrary.search.view.SearchResultFragment.ARG_IS_GLOBAL_SEARCH;

/**
 * The main Class for browsing books to download
 * its display depends on the display width
 * may display one ,two or three pans each including the suitable fragment
 * fragments that don't have room to be displayed displayed in new activities
 */
public class BrowsingActivity
        extends AppCompatActivity
        implements BookCategoryFragment.OnCategoryItemClickListener,
        AuthorListFragment.OnAuthorItemClickListener,
        LibraryFragment.OnBookFilterPagerPageChangedListener,
        SearchRequestPopupFragment.OnSearchPopupFragmentInteractionListener,
        NavigationView.OnNavigationItemSelectedListener,
        BookCardEventListener,
        ConfirmBatchDownloadDialogFragment.BatchDownloadConfirmationListener,
        ConfirmBookDeleteDialogFragment.BookDeleteDialogListener,
        BrowsingActivityNavigationController.BrowsingActivityControllerListener,
        BookCollectionsController.BookCollectionsControllerCallback,
        RenameCollectionDialogFragment.RenameCollectionListener,
        GlobalUserNotesFragment.GlobalUserNotesFragmentListener,
        DonationReminderDialogFragment.DonationReminderDialogFragmentDelegate {

    public static final int AUTHOR_LIST_FRAGMENT_TYPE = 0;
    public static final int BOOK_CATEGORY_FRAGMENT_TYPE = 1;
    public static final int BOOK_LIST_FRAGMENT_TYPE = 2;
    public static final int BOOK_INFORMATION_TYPE = 3;
    public static final int HOME_SCREEN_TYPE = 4;

    public static final int ALL_BOOKS_TYPE = -1;

    public static final String NUMBER_OF_PANS_KEY = "NUMBER_OF_PANS_KEY";
    public static final String BOOK_LIST_FRAGMENT_TAG = "BookListFragment";
    public static final String BOOK_INFORMATION_FRAGMENT_TAG = "BookInformationFragment";
    public static final String KEY_NUMBER_OF_BOOKS_TO_DONLOAD = "KEY_NUMBER_OF_BOOKS_TO_DONLOAD";
    protected static final String TAG = "BrowsingActivity";
    protected static final String KEY_DOWNLOADED_ONLY = "shared_pref_download_only_Key";
    static final String BOOK_LIST_FRAGMENT_ADDED = "BOOK_LIST_FRAGMENT_ADDED";
    static final String BOOK_INFORMATION_FRAGMENT_ADDED = "BOOK_INFORMATION_FRAGMENT_ADDED";
    protected int mPaneNumber;
    @NonNull
    protected HashSet<Integer> selectedBooksIds = new HashSet<>();
    @Nullable
    protected BookSelectionActionModeCallback mActionMode;
    protected boolean mIsArabic;
    protected IconSwitch toolbarDownloadOnlySwitch;
    protected boolean mShouldDisplayDownloadOnly;
    protected SwitchCompat navDownloadedOnlySwitch;
    @NonNull
    protected List<BrowsingActivityListingFragment> pagerTabs = new ArrayList<>();
    protected SearchView mSearchView;
    /**
     * this variable is here to be overrided in subclasses to allow calling activity super constructors
     */
    View bookListContainer;
    @Nullable
    BooksInformationDbHelper mBooksInformationDbHelper;
    @Nullable
    private BrowsingActivityNavigationController browsingActivityNavigationController;
    @NonNull
    private HashSet<Integer> mBooksToDownload = new HashSet<>();
    private BrowsingAnalyticsController browsingAnalyticsController;
    @Nullable
    private BookCardEventsCallback bookCardEventsCallback = new BookCardEventsCallback(this) {
        @Override
        public boolean OnBookItemLongClicked(int bookId) {
            if (mActionMode != null) {
                return false;
            }

            mActionMode = new BookSelectionActionModeCallback();
            mActionMode.startBookSelectionActionMode(BrowsingActivity.this);
            selectedBooksIds.add(bookId);
            notifySelectionStateChanged(BOOK_LIST_FRAGMENT_TYPE);
            return true;
        }

        @Override
        public boolean isBookSelected(int bookId) {
            return selectedBooksIds.contains(bookId);
        }

        @Override
        public void bookSelected(int bookId, boolean checked) {
            if (checked) {
                selectedBooksIds.add(bookId);
                notifySelectionStateChanged(BOOK_LIST_FRAGMENT_TYPE);
            } else {
                selectedBooksIds.remove(bookId);
                notifySelectionStateChanged(BOOK_LIST_FRAGMENT_TYPE);
            }
        }

        @Override
        public boolean shouldDisplayDownloadedOnly() {
            return BrowsingActivity.this.shouldDisplayDownloadedOnly();
        }

        @Override
        public void mayBeSetTitle(String title) {
            BrowsingActivity.this.mayBeSetTitle(title);
        }

        @Override
        public void showAllAuthorBooks(@NonNull AuthorInfo authorInfo) {
            BrowsingActivity.this.OnAuthorItemItemClick(authorInfo);
        }

        @Override
        public void showAllCategoryBooks(@NonNull BookCategory category) {
            BrowsingActivity.this.OnCategoryItemClick(category);
        }

        @Override
        public void showAllCollectionBooks(@NonNull BooksCollection booksCollection) {
            BookListFragment fragment = BookListFragment.newInstance(
                    BookListFragment.FILTER_BY_COLLECTION,
                    booksCollection.getCollectionsId(),
                    booksCollection.getName());
            if (browsingActivityNavigationController != null) {
                browsingActivityNavigationController.showCollectionDetails(fragment);
            }
        }

        @Override
        public void selectAllCategoryBooks(int CategoryId) {
            BrowsingActivity.this.onCategorySelected(CategoryId, true);

        }

        @Override
        public void selectAllAuthorsBooks(int authorId) {
            BrowsingActivity.this.onAuthorSelected(authorId, true);
        }

        @Override
        public void selectAllCollectionBooks(BooksCollection booksCollection) {
            if (mActionMode == null) {
                mActionMode = new BookSelectionActionModeCallback();
                mActionMode.startBookSelectionActionMode(BrowsingActivity.this);
            }
            UserDataDBHelper.GlobalUserDBHelper userDBHelper = UserDataDBHelper.getInstance(context);
            selectedBooksIds.addAll(userDBHelper.getBooksSetCollectionId(booksCollection, shouldDisplayDownloadedOnly()));
            notifySelectionStateChanged();
        }

        @Override
        protected void notifyBookDownloadFailed(int bookId, String failurReason) {
            BrowsingActivity.this.notifyBookDownloadFailed(bookId, failurReason);

        }


        @Override
        public void notifyBookDownloadStatusUpdate(int bookId, int downloadStatus) {
            BrowsingActivity.this.notifyBookDownloadStatusUpdate(bookId, downloadStatus);
        }

        @Override
        public void notifyBookDownloadStatusUpdate() {
            notifyActivityRestarted();
        }


        @Override
        public boolean isInSelectionMode() {
            return BrowsingActivity.this.isInSelectionMode();
        }

        @Override
        public void OnBookTitleClick(int bookId, String bookTitle) {
            if (browsingActivityNavigationController != null) {
                browsingActivityNavigationController.showBookInformationFragment(BookInformationFragment.newInstance(bookId));
            }
            browsingAnalyticsController.logBookSelectionEvent(bookId);
        }


    };
    private AppBarLayout appBarLayout;
    private ActionBarDrawerToggle actionBarDrawerToggle;
    @NonNull
    private ArrayList<BookCollectionsCallBack> bookCollectionsCallBack = new ArrayList<>();
    private AppRateController appRateController;

    private void notifyBookDownloadFailed(int bookId, String failurReason) {
        CoordinatorLayout coordinatorLayout = findViewById(R.id.browsing_coordinator_layout);
        Snackbar mySnackbar = Snackbar.make(coordinatorLayout,
                getResources().getString(R.string.book_download_failure, mBooksInformationDbHelper.getBookName(bookId)),
                Snackbar.LENGTH_LONG);
        mySnackbar.setAction(R.string.redownload,
                v -> {
                    bookCardEventsCallback.startDownloadingBook(mBooksInformationDbHelper.getBookInfo(bookId));
                    bookCardEventsCallback.notifyBookDownloadStatusUpdate(bookId, DownloadsConstants.STATUS_DOWNLOAD_REQUESTED);
                }
        );
        mySnackbar.show();
    }

    @Override
    public synchronized void registerListener(BrowsingActivityListingFragment pagerTab) {
        pagerTabs.add(pagerTab);

    }

    @Override
    public synchronized void unRegisterListener(BrowsingActivityListingFragment pagerTab) {
        pagerTabs.remove(pagerTab);

    }

    @Override
    protected void onResume() {
        super.onResume();
        Util.restartIfLocaleChanged(this, mIsArabic);

    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ((IslamicLibraryApplication) getApplication()).refreshLocale(this, false);
        mIsArabic = Util.isArabicUi(this);
        super.onCreate(savedInstanceState);
        bookCardEventsCallback.intializeListener();

        browsingAnalyticsController = new BrowsingAnalyticsController(this);
        inflateUi(savedInstanceState);
    }


    protected void inflateUi(@Nullable Bundle savedInstanceState) {
        setContentView(R.layout.activity_browsing);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        DrawerArrowDrawable drawerArrow = new DrawerArrowDrawable(this);
        drawerArrow.setColor(0xFFFFFF);


        toolbar.setNavigationIcon(drawerArrow);
        ActionBar supportActionBar = getSupportActionBar();
        if (supportActionBar != null) {
            supportActionBar.setDisplayHomeAsUpEnabled(true);
            supportActionBar.setDisplayShowTitleEnabled(false);
        }
        mBooksInformationDbHelper = BooksInformationDbHelper.getInstance(BrowsingActivity.this);
        appBarLayout = findViewById(R.id.appBar);

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        actionBarDrawerToggle = new ActionBarDrawerToggle(
                this, drawer, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(actionBarDrawerToggle);
        actionBarDrawerToggle.syncState();

        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);


        toolbarDownloadOnlySwitch = findViewById(R.id.toolbar_downloaded_only_switch);
        navDownloadedOnlySwitch = (SwitchCompat) navigationView.getMenu().findItem(R.id.nav_item_downloaded_only).getActionView();

        SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
        mShouldDisplayDownloadOnly = sharedPref.getBoolean(KEY_DOWNLOADED_ONLY, false);
        setToolbarDownloadOnlySwitchNoCallBack(mShouldDisplayDownloadOnly);
        setDownloadOnlySwitchNoCallBack(mShouldDisplayDownloadOnly);

        toolbarDownloadOnlySwitch.setCheckedChangeListener(v -> switchDownloadOnlyFilter(!shouldDisplayDownloadedOnly()));
        navDownloadedOnlySwitch.setOnCheckedChangeListener((buttonView, isChecked) -> switchDownloadOnlyFilter(isChecked));

        //this is done to prevent motion of drawer when the user tries to slide thes switch
        navDownloadedOnlySwitch.setOnTouchListener((v, event) -> {
            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                v.getParent().requestDisallowInterceptTouchEvent(true);
            }
            return false;
        });

        View filterPagerContainer = findViewById(R.id.filter_pager_container);
        bookListContainer = findViewById(R.id.book_list_container);
        View bookInfoContainer = findViewById(R.id.book_info_container);
        FragmentManager fragmentManager = getSupportFragmentManager();


        mPaneNumber = getmumberOfpans(filterPagerContainer, bookInfoContainer);

        @Nullable
        BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);

        int oldPanNumbers = savedInstanceState == null ? 0 : savedInstanceState.getInt(NUMBER_OF_PANS_KEY);

        browsingActivityNavigationController = BrowsingActivityNavigationController.create(
                mPaneNumber,
                oldPanNumbers,
                fragmentManager,
                savedInstanceState != null,
                this,
                bottomNavigationView,
                this);
        if (browsingActivityNavigationController != null) {
            browsingActivityNavigationController.intiializePans();
            if (bottomNavigationView != null) {
                bottomNavigationView.setOnNavigationItemSelectedListener(browsingActivityNavigationController::handleButtomNavigationItem);
            }
        }

        appRateController = new AppRateController(this);

        appRateController
                .monitor()
                .showRateDialogIfMeetsConditions(this);
    }

    public void setAppbarExpanded(boolean expanded) {
        appBarLayout.setExpanded(expanded);
    }

    @Override
    public void setUpNavigation(boolean zeroBackStack) {
        ActionBar actionBar = getSupportActionBar();
        if (zeroBackStack && actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(false);
            actionBarDrawerToggle.setDrawerIndicatorEnabled(false);
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setDisplayShowHomeEnabled(true);
            actionBarDrawerToggle.setToolbarNavigationClickListener(v -> onBackPressed());
        } else {
            actionBarDrawerToggle.setDrawerIndicatorEnabled(true);
            actionBarDrawerToggle.setToolbarNavigationClickListener(null);
        }

    }

    private int getmumberOfpans(@Nullable View filterPagerContainer, @Nullable View bookInfoContainer) {
        int paneNumber = 0;
        if (filterPagerContainer != null && filterPagerContainer.getVisibility() == View.VISIBLE) {
            paneNumber = 1;
            if (bookListContainer != null && bookListContainer.getVisibility() == View.VISIBLE) {
                paneNumber = 2;
                if (bookInfoContainer != null && bookInfoContainer.getVisibility() == View.VISIBLE) {
                    paneNumber = 3;
                }
            }
        }
        return paneNumber;
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(NUMBER_OF_PANS_KEY, mPaneNumber);
    }

    protected void switchDownloadOnlyFilter(boolean showDownloadedOnly) {
        if (showDownloadedOnly) {
            if (selectedBooksIds != null && !selectedBooksIds.isEmpty()) {
                selectedBooksIds.retainAll(
                        mBooksInformationDbHelper.getBooksIdsFilteredOnDownloadStatus(
                                BooksInformationDBContract.StoredBooks.COLUMN_NAME_STATUS + ">=?",
                                new String[]{String.valueOf(DownloadsConstants.STATUS_FTS_INDEXING_ENDED)}
                        ));
            }

        }

        if (mActionMode != null) {
            mActionMode.getMenu().findItem(R.id.batch_download).setVisible(!showDownloadedOnly).setEnabled(!showDownloadedOnly);
            mActionMode.getMenu().findItem(R.id.select_all).setVisible(showDownloadedOnly).setEnabled(showDownloadedOnly);

        }
        mShouldDisplayDownloadOnly = showDownloadedOnly;
        setToolbarDownloadOnlySwitchNoCallBack(showDownloadedOnly);
        setDownloadOnlySwitchNoCallBack(showDownloadedOnly);

        SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putBoolean(KEY_DOWNLOADED_ONLY, showDownloadedOnly);
        editor.apply();


        mShouldDisplayDownloadOnly = sharedPref.getBoolean(KEY_DOWNLOADED_ONLY, false);

        notifyDownloadedOnly(showDownloadedOnly);
    }

    protected void setDownloadOnlySwitchNoCallBack(boolean showDownloadedOnly) {
        if (navDownloadedOnlySwitch != null) {
            navDownloadedOnlySwitch.setOnCheckedChangeListener(null);
            navDownloadedOnlySwitch.setChecked(showDownloadedOnly);
            navDownloadedOnlySwitch.setOnCheckedChangeListener((buttonView, isChecked) -> switchDownloadOnlyFilter(isChecked));
        }
    }

    protected void setToolbarDownloadOnlySwitchNoCallBack(boolean showDownloadedOnly) {
        if (toolbarDownloadOnlySwitch != null) {
            toolbarDownloadOnlySwitch.setCheckedChangeListener(null);
            toolbarDownloadOnlySwitch.setChecked(showDownloadedOnly ? IconSwitch.Checked.LEFT : IconSwitch.Checked.RIGHT);
            toolbarDownloadOnlySwitch.setCheckedChangeListener(v -> switchDownloadOnlyFilter(!shouldDisplayDownloadedOnly()));
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_browsing, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        if (id == R.id.action_settings) {
            Intent intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);
            return true;
        } else if (id == R.id.refresh_with_file_system) {
            RefreshBooksWithDirectoryService.startActionRefreshEveryThing(this);
            Toast.makeText(this, R.string.refreshing_on_background, Toast.LENGTH_LONG).show();
            return true;
        } else if (id == android.R.id.home) {
            if (actionBarDrawerToggle != null && !actionBarDrawerToggle.onOptionsItemSelected(item)) {
                super.onBackPressed();

            }
            //Toast.makeText(this, mActionMode == null ? "true" : "false", Toast.LENGTH_LONG).show();
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void OnCategoryItemClick(@NonNull BookCategory bookCategory) {
        BookListFragment fragment = BookListFragment.newInstance(
                BookListFragment.FILTERBYCATEGORY,
                bookCategory.getId(),
                bookCategory.getName());
        if (browsingActivityNavigationController != null) {
            browsingActivityNavigationController.showCategoryDetails(fragment);
        }
        browsingAnalyticsController.logCategoryEvent(bookCategory);
    }

    @Override
    public boolean OnCategoryItemLongClicked(int categoryId) {
        if (mActionMode != null) {
            return false;
        }


        mActionMode = new BookSelectionActionModeCallback();
        mActionMode.startBookSelectionActionMode(this);
        addSelectedCategory(categoryId);
        return true;

    }

    @Override
    public void onCategorySelected(int categoryId, boolean checked) {
        if (checked) {
            addSelectedCategory(categoryId);
        } else {
            removeSelectedCategory(categoryId);
        }
    }

    protected void removeSelectedCategory(int categoryId) {
        selectedBooksIds.removeAll(mBooksInformationDbHelper.getBooksIdsSetByCategoryId(categoryId, shouldDisplayDownloadedOnly()));
        notifySelectionStateChanged(BOOK_CATEGORY_FRAGMENT_TYPE);
    }

    protected void addSelectedCategory(int categoryId) {
        selectedBooksIds.addAll(mBooksInformationDbHelper.getBooksIdsSetByCategoryId(categoryId, shouldDisplayDownloadedOnly()));
        notifySelectionStateChanged(BOOK_CATEGORY_FRAGMENT_TYPE);
    }

    protected void addAllBooksToSelection(boolean downloadedOnly) {
        if (downloadedOnly) {
            selectedBooksIds.addAll(mBooksInformationDbHelper.getBookIdsDownloadedOnly());
        } else {
            selectedBooksIds.addAll(mBooksInformationDbHelper.getAllBookIds());
        }
        notifySelectionStateChanged(ALL_BOOKS_TYPE);
    }

    protected void removeAllSelectedBooks() {
        selectedBooksIds.clear();
        notifySelectionStateChanged(ALL_BOOKS_TYPE);
    }

    @Override
    public boolean isCategorySelected(int categoryId) {
        return selectedBooksIds.containsAll(mBooksInformationDbHelper.getBooksIdsSetByCategoryId(categoryId, shouldDisplayDownloadedOnly()));
    }

    protected void addSelectedAuthor(int authorId) {
        selectedBooksIds.addAll(mBooksInformationDbHelper.getBooksSetAuthorId(authorId, shouldDisplayDownloadedOnly()));
        notifySelectionStateChanged(AUTHOR_LIST_FRAGMENT_TYPE);
    }

    protected void removeSelectedAuthor(int authorId) {
        selectedBooksIds.removeAll(mBooksInformationDbHelper.getBooksSetAuthorId(authorId, shouldDisplayDownloadedOnly()));
        notifySelectionStateChanged(AUTHOR_LIST_FRAGMENT_TYPE);

    }

    @Override
    public boolean isAuthorSelected(int authorId) {
        return selectedBooksIds.containsAll(mBooksInformationDbHelper.getBooksSetAuthorId(authorId, shouldDisplayDownloadedOnly()));
    }

    @Override
    public void onAuthorSelected(int authorId, boolean checked) {
        if (checked) {
            addSelectedAuthor(authorId);
        } else {
            removeSelectedAuthor(authorId);
        }
    }

    @Override
    public boolean OnAuthorItemLongClicked(int authorId) {
        if (mActionMode != null) {
            return false;
        }
        mActionMode = new BookSelectionActionModeCallback();
        mActionMode.startBookSelectionActionMode(this);
        addSelectedAuthor(authorId);
        return true;
    }

    @Override
    public boolean shouldDisplayDownloadedOnly() {
        return mShouldDisplayDownloadOnly;
    }

    @Override
    public boolean isInSelectionMode() {
        return mActionMode != null;
    }

    @Override
    public void mayBeSetTitle(@Nullable String title) {
        if (mPaneNumber == 1) {
            ActionBar actionBar = getSupportActionBar();
            if (actionBar != null) {
                if (title != null && !title.isEmpty()) {
                    actionBar.setDisplayShowTitleEnabled(true);
                    actionBar.setTitle(title);
                } else {
                    actionBar.setDisplayShowTitleEnabled(false);
                }
            }
        }
    }


    @Override
    public void OnAuthorItemItemClick(@NonNull AuthorInfo authorInfo) {
        BookListFragment fragment = BookListFragment.newInstance(BookListFragment.FILTERBYAuthour,
                authorInfo.getId(),
                authorInfo.getName());
        if (browsingActivityNavigationController != null) {
            browsingActivityNavigationController.showAuthorFragment(fragment);
        }
        browsingAnalyticsController.logAuthorBooksList(authorInfo);
    }


    @Override
    public void OnFilterAllSelected(boolean b) {
        if (mPaneNumber > 1) {
            bookListContainer.setVisibility(b ? View.GONE : View.VISIBLE);
        }
    }

    public synchronized void registerPagerFragment(LibraryFragment libraryFragment) {
        if (browsingActivityNavigationController != null) {
            browsingActivityNavigationController.registerPagerFragment(libraryFragment);
        }
    }

    protected synchronized void notifySelectionActionModeDestroyed() {
        for (BrowsingActivityListingFragment pagerTab : pagerTabs) {
            pagerTab.actionModeDestroyed();
        }

    }

    protected synchronized void notifySelectionStateChanged(int type) {
        for (int tab_number = 0; tab_number < pagerTabs.size(); tab_number++) {
            BrowsingActivityListingFragment pagerTab = pagerTabs.get(tab_number);
            if (pagerTab.getType() != type)
                pagerTab.bookSelectionStatusUpdate();
        }


    }

    private synchronized void notifySelectionStateChanged() {
        for (int tab_number = 0; tab_number < pagerTabs.size(); tab_number++) {
            BrowsingActivityListingFragment pagerTab = pagerTabs.get(tab_number);
            pagerTab.bookSelectionStatusUpdate();
        }
    }

    protected synchronized void notifySelectionActionModeSarted() {
        for (BrowsingActivityListingFragment pagerTab : pagerTabs) {
            pagerTab.actionModeStarted();
        }

    }

    @Override
    public void onCollectionRenamed(BooksCollection bookCollection, String newName) {
        for (BookCollectionsCallBack collectionsCallBack : bookCollectionsCallBack) {
            if (collectionsCallBack != null)
                collectionsCallBack.onBookCollectionRenamed(bookCollection, newName);
        }
    }


    @Override
    public synchronized void notifyBookCollectionCahnged(BooksCollection booksCollection) {
        for (BookCollectionsCallBack collectionsCallBack : bookCollectionsCallBack) {
            if (collectionsCallBack != null)
                collectionsCallBack.onBookCollectionCahnged(booksCollection);
        }
    }

    @Override
    public synchronized void registerBookCollectionCallBack(BookCollectionsCallBack bookCollectionsCallBack) {
        this.bookCollectionsCallBack.add(bookCollectionsCallBack);
    }

    @Override
    public synchronized void unRegisterBookCollectionCallBack(BookCollectionsCallBack bookCollectionsCallBack) {
        this.bookCollectionsCallBack.remove(bookCollectionsCallBack);
    }

    @Override
    public synchronized void notifyCollectionAdded(BooksCollection booksCollection) {
        for (BookCollectionsCallBack collectionsCallBack : bookCollectionsCallBack) {
            if (collectionsCallBack != null)
                collectionsCallBack.onBookCollectionAdded(booksCollection);
        }

    }

    @Override
    public synchronized void notifyCollectionRemoved(BooksCollection booksCollection) {
        for (BookCollectionsCallBack collectionsCallBack : bookCollectionsCallBack) {
            if (collectionsCallBack != null)
                collectionsCallBack.onBookCollectionRemoved(booksCollection);
        }
    }


    @Override
    public synchronized void notifyBookCollectionMoved(int collectionsId, int oldPosition, int newPosition) {
        for (BookCollectionsCallBack collectionsCallBack : bookCollectionsCallBack) {
            if (collectionsCallBack != null)
                collectionsCallBack.onBookCollectionMoved(collectionsId,
                        oldPosition,
                        newPosition);
        }
    }

    @Override
    public void showRenameDialog(@NonNull BooksCollection booksCollection) {
        Bundle confirmBatchDownloadDialogFragmentBundle = new Bundle();
        confirmBatchDownloadDialogFragmentBundle.putString(KEY_OLD_NAME, booksCollection.getName());
        Gson gson = new Gson();
        String json = gson.toJson(booksCollection);
        confirmBatchDownloadDialogFragmentBundle.putString(KEY_COLLECTION_GSON, json);
        DialogFragment renameCollectionDialogFragment = new RenameCollectionDialogFragment();
        renameCollectionDialogFragment.setArguments(confirmBatchDownloadDialogFragmentBundle);
        renameCollectionDialogFragment.show(getSupportFragmentManager(), "renameCollectionDialogFragment");

    }

    @Override
    public synchronized void notifyCollectionVisibilityChanged(BooksCollection booksCollection, boolean isVisible) {
        for (BookCollectionsCallBack collectionsCallBack : bookCollectionsCallBack) {
            if (collectionsCallBack != null)
                collectionsCallBack.onBookCollectionVisibilityChanged(booksCollection,
                        isVisible);
        }
    }

    private void notifyActivityRestarted() {
        for (BrowsingActivityListingFragment pagerTab : pagerTabs) {
            pagerTab.reAcquireCursors();
        }
    }

    private void notifyActivityStopped() {
        for (BrowsingActivityListingFragment pagerTab : pagerTabs) {
            pagerTab.closeCursors();
        }
    }

    protected synchronized void notifyDownloadedOnly(boolean checked) {
        for (BrowsingActivityListingFragment pagerTab : pagerTabs) {
            pagerTab.switchTodownloadedOnly(checked);
        }

    }

    public synchronized void notifyBookDownloadStatusUpdate(int bookId, int downloadStatus) {

        for (BrowsingActivityListingFragment pagerTab : pagerTabs) {
            pagerTab.BookDownloadStatusUpdate(bookId, downloadStatus);
        }

    }

    public void unRegisterPagerFragment() {
        if (browsingActivityNavigationController != null) {
            browsingActivityNavigationController.unRegisterPagerFragment();
        }

    }

    @Override
    public void onFragmentSearchClicked() {
        Toast.makeText(this, "dialog dismissed", Toast.LENGTH_LONG).show();
    }

    protected void startSearch(String SearchQuery) {
        Intent searchIntent = new Intent(this, SearchResultActivity.class);
        searchIntent.setAction(Intent.ACTION_SEARCH);
        Bundle bundle = new Bundle();
        bundle.putBoolean(ARG_IS_GLOBAL_SEARCH, true);
        ArrayList<Integer> selectedSearchableBooks = new ArrayList<>();

        if (shouldDisplayDownloadedOnly()) {
            selectedSearchableBooks.addAll(selectedBooksIds);
        } else {
            HashSet<Integer> downloadedHashSet = mBooksInformationDbHelper.getBookIdsDownloadedOnly();
            downloadedHashSet.retainAll(selectedBooksIds);

            if (downloadedHashSet.size() == 0) {
                Toast.makeText(this, R.string.no_downloaded_selected_books, Toast.LENGTH_SHORT).show();
                return;
            } else {
                if (downloadedHashSet.size() < selectedBooksIds.size()) {
                    Toast.makeText(this, R.string.searching_downloaded_only, Toast.LENGTH_SHORT).show();
                }
                selectedSearchableBooks.addAll(downloadedHashSet);
            }
        }

        bundle.putIntegerArrayList(SearchResultFragment.ARG_SEARCHABLE_BOOKS, selectedSearchableBooks);
        bundle.putString(SearchManager.QUERY, SearchQuery);
        searchIntent.putExtras(bundle);

        startActivity(searchIntent);
    }

    @Override
    public boolean onSearchRequested() {
        //https://developer.android.com/guide/topics/search/search-dialog.html#SearchContextData
        Bundle appData = new Bundle();
        appData.putBoolean(ARG_IS_GLOBAL_SEARCH, true);
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.addAll(selectedBooksIds);
        appData.putIntegerArrayList(SearchResultFragment.ARG_SEARCHABLE_BOOKS, arrayList);
        startSearch(null, false, appData, false);
        return true;
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_settings) {
            Intent intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);
        } else if (id == R.id.search_inside_books) {
            startActionModeFromDrawer();
            mSearchView.setIconified(false);
            // Toast.makeText(this, R.string.select_books_authors_or_cat, Toast.LENGTH_SHORT).show();
        } else if (id == R.id.nav_item_in_progress_downloads) {
            Intent i = new Intent(this, DownloadProgressActivity.class);
            this.startActivity(i);
        } else if (id == R.id.start_multi_book_selection) {
            startActionModeFromDrawer();
        } else if (id == R.id.nav_rate_app) {
            AboutUtil.rateApp(this);
        } else if (id == R.id.nav_share_app) {
            AboutUtil.ShareAppLink(this);
        } else if (id == R.id.nav_feedback) {
            AboutUtil.sendFeedBack(this);
        } else if (id == R.id.nav_help) {
            Intent intent = new Intent(this, HelpActivity.class);
            startActivity(intent);
        } else if (id == R.id.nav_pay) {
            AboutUtil.pay(this);
        } else if (id == R.id.nav_about_app) {
            Intent intent = new Intent(this, AboutActivity.class);
            startActivity(intent);
        } else if (id == R.id.nav_item_downloaded_only) {
            SwitchCompat downloadedOnlySwitch = (SwitchCompat) item.getActionView();
            downloadedOnlySwitch.toggle();
        }

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    private void startActionModeFromDrawer() {
        if (mActionMode != null) {
            return;
        }

        mActionMode = new BookSelectionActionModeCallback();
        mActionMode.startBookSelectionActionMode(this);
        notifySelectionActionModeSarted();
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        if (drawer != null && drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else if (isInSelectionMode()) {
            mayBecloseSelectionMode();
        } else {
            super.onBackPressed();
        }
    }

    private void mayBecloseSelectionMode() {
        if (browsingActivityNavigationController != null) {
            if (browsingActivityNavigationController.shouldCloseSelectionMode()) {
                mActionMode.onDestroyActionMode();
            } else {
                super.onBackPressed();
            }
        }


    }

    @Override
    protected void onDestroy() {
        bookCardEventsCallback.removeBookDownloadBroadcastListener();
        if (browsingActivityNavigationController != null) {
            browsingActivityNavigationController.onDestroy();
        }
        notifyActivityStopped();
        super.onDestroy();
    }

//    @Override
//    protected void onRestart() {
//        super.onRestart();
//        notifyActivityRestarted();
//    }

    @Nullable
    @Override
    public BookCardEventsCallback getBookCardEventCallback() {
        return bookCardEventsCallback;
    }

    public void startBatchDownload() {
        BooksDownloader booksDownloader = new BooksDownloader(BrowsingActivity.this);
        booksDownloader.downloadBookCollection(mBooksToDownload.toArray(new Integer[mBooksToDownload.size()]));
    }

    @Override
    public void onDialogPositiveClick() {
        startBatchDownload();
    }

    @Override
    public void onBookDeleteDialogDialogPositiveClick(int bookId) {
        bookCardEventsCallback.onBookDeleteConfirmation(bookId);
    }

    @Override
    public void showSnackBarBookNotDownloaded(int bookId) {
        CoordinatorLayout coordinatorLayout = findViewById(R.id.browsing_coordinator_layout);
        Snackbar mySnackbar = Snackbar.make(coordinatorLayout,
                getResources().getString(R.string.book_not_download, mBooksInformationDbHelper.getBookName(bookId)),
                Snackbar.LENGTH_LONG);
        mySnackbar.setAction(R.string.redownload,
                v -> {
                    bookCardEventsCallback.startDownloadingBook(mBooksInformationDbHelper.getBookInfo(bookId));
                    bookCardEventsCallback.notifyBookDownloadStatusUpdate(bookId, DownloadsConstants.STATUS_DOWNLOAD_REQUESTED);
                }
        );
        mySnackbar.show();
    }

    @Override
    public DonationReminderDialogFragment.DonationReminderDialogFragmentListener getListener() {
        return appRateController.getListener();
    }


    private class BookSelectionActionModeCallback {

        private Menu menu;
        private Toolbar selectionToolBar;

        boolean onActionItemClicked(@NonNull MenuItem item) {
            if (item.getItemId() == R.id.batch_download) {
                mBooksToDownload.clear();
                mBooksToDownload.addAll(selectedBooksIds);
                HashSet<Integer> downloadedHashSet = mBooksInformationDbHelper.getBooksIdsFilteredOnDownloadStatus(
                        BooksInformationDBContract.StoredBooks.COLUMN_NAME_STATUS + ">?",
                        new String[]{String.valueOf(DownloadsConstants.STATUS_DOWNLOAD_STARTED)}
                );
                boolean isSelectionModified = mBooksToDownload.removeAll(downloadedHashSet);

                if (mBooksToDownload.size() != 0) {
                    if (mBooksToDownload.size() == 1) {
                        startBatchDownload();
                        onDestroyActionMode();
                    } else {
                        if (isSelectionModified) {
                            Toast.makeText(BrowsingActivity.this, R.string.removed_selection_of_downloaded_books, Toast.LENGTH_LONG).show();
                        }

                        Bundle confirmBatchDownloadDialogFragmentBundle = new Bundle();
                        confirmBatchDownloadDialogFragmentBundle.putInt(KEY_NUMBER_OF_BOOKS_TO_DONLOAD, mBooksToDownload.size());
                        DialogFragment confirmBatchDownloadDialogFragment = new ConfirmBatchDownloadDialogFragment();
                        confirmBatchDownloadDialogFragment.setArguments(confirmBatchDownloadDialogFragmentBundle);
                        confirmBatchDownloadDialogFragment.show(getSupportFragmentManager(), "ConfirmBatchDownloadDialogFragment");
                        onDestroyActionMode();
                    }
                } else {
                    Toast.makeText(BrowsingActivity.this, R.string.toast_all_selected_books_already_downlaoded, Toast.LENGTH_LONG).show();
                }

            } else if (item.getItemId() == R.id.select_all) {
                addAllBooksToSelection(shouldDisplayDownloadedOnly());
            } else if (item.getItemId() == R.id.clear_selection) {
                removeAllSelectedBooks();
            }

            return false;
        }


        void onDestroyActionMode() {
            mActionMode = null;
            selectedBooksIds.clear();
            selectionToolBar.setVisibility(View.GONE);
            notifySelectionActionModeDestroyed();
        }

        void startBookSelectionActionMode(@NonNull final BrowsingActivity browsingActivity) {
            selectionToolBar = browsingActivity.findViewById(R.id.selection_tool_bar);
            menu = selectionToolBar.getMenu();
            if (menu == null || !menu.hasVisibleItems()) {
                selectionToolBar.inflateMenu(R.menu.book_selection_action_menu);
                selectionToolBar.findViewById(R.id.up_button).setOnClickListener(v -> {
                    if (mActionMode != null) mActionMode.onDestroyActionMode();
                });

                menu = selectionToolBar.getMenu();
                selectionToolBar.setOnMenuItemClickListener(this::onActionItemClicked);
            }
            selectionToolBar.showOverflowMenu();

            browsingActivity.notifySelectionActionModeSarted();
            boolean displayDownloadOnly = browsingActivity.shouldDisplayDownloadedOnly();
            menu.findItem(R.id.batch_download)
                    .setEnabled(!displayDownloadOnly)
                    .setVisible(!displayDownloadOnly);
            menu.findItem(R.id.select_all)
                    .setEnabled(displayDownloadOnly)
                    .setVisible(displayDownloadOnly);

            browsingActivity.mSearchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
            browsingActivity.mSearchView.setQueryHint(browsingActivity.getString(R.string.hint_search_inside_books));

            selectionToolBar.setVisibility(View.VISIBLE);
            //   mSearchView.setIconifiedByDefault(true);
            browsingActivity.mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String s) {
                    browsingActivity.startSearch(s);
                    return true;
                }

                @Override
                public boolean onQueryTextChange(String s) {
                    return false;
                }
            });

        }

        public Menu getMenu() {
            return menu;
        }
    }


}