/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.documentsui.dirlist;

import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.State.MODE_GRID;
import static com.android.documentsui.State.MODE_LIST;
import static com.android.documentsui.State.SORT_ORDER_UNKNOWN;
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import static com.android.documentsui.model.DocumentInfo.getCursorString;

import android.annotation.IntDef;
import android.annotation.StringRes;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ClipData;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.support.v13.view.DragStartHelper;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.GridLayoutManager.SpanSizeLookup;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.RecyclerListener;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.text.BidiFormatter;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.ActionMode;
import android.view.ContextMenu;
import android.view.DragEvent;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toolbar;

import com.android.documentsui.BaseActivity;
import com.android.documentsui.DirectoryLoader;
import com.android.documentsui.DirectoryResult;
import com.android.documentsui.DocumentsActivity;
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.Events.InputEvent;
import com.android.documentsui.Events.MotionInputEvent;
import com.android.documentsui.ItemDragListener;
import com.android.documentsui.MenuManager;
import com.android.documentsui.Menus;
import com.android.documentsui.MessageBar;
import com.android.documentsui.Metrics;
import com.android.documentsui.MimePredicate;
import com.android.documentsui.R;
import com.android.documentsui.RecentsLoader;
import com.android.documentsui.RetainedState;
import com.android.documentsui.RootsCache;
import com.android.documentsui.Shared;
import com.android.documentsui.Snackbars;
import com.android.documentsui.State;
import com.android.documentsui.State.ViewMode;
import com.android.documentsui.ThumbnailCache;
import com.android.documentsui.clipping.DocumentClipper;
import com.android.documentsui.clipping.UrisSupplier;
import com.android.documentsui.dirlist.MultiSelectManager.Selection;
import com.android.documentsui.dirlist.UserInputHandler.DocumentDetails;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.RootInfo;
import com.android.documentsui.services.FileOperation;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperationService.OpType;
import com.android.documentsui.services.FileOperations;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

import javax.annotation.Nullable;

/**
 * Display the documents inside a single directory.
 */
public class DirectoryFragment extends Fragment
        implements DocumentsAdapter.Environment, LoaderCallbacks<DirectoryResult>,
        ItemDragListener.DragHost, SwipeRefreshLayout.OnRefreshListener {

    @IntDef(flag = true, value = {
            TYPE_NORMAL,
            TYPE_RECENT_OPEN
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ResultType {}
    public static final int TYPE_NORMAL = 1;
    public static final int TYPE_RECENT_OPEN = 2;

    @IntDef(flag = true, value = {
            REQUEST_COPY_DESTINATION
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface RequestCode {}
    public static final int REQUEST_COPY_DESTINATION = 1;

    private static final String TAG = "DirectoryFragment";
    private static final int LOADER_ID = 42;

    private static final int CACHE_EVICT_LIMIT = 100;
    private static final int REFRESH_SPINNER_DISMISS_DELAY = 500;

    private Model mModel;
    private MultiSelectManager mSelectionMgr;
    private Model.UpdateListener mModelUpdateListener = new ModelUpdateListener();
    private UserInputHandler<InputEvent> mInputHandler;
    private SelectionModeListener mSelectionModeListener;
    private FocusManager mFocusManager;

    private IconHelper mIconHelper;

    private SwipeRefreshLayout mRefreshLayout;
    private View mEmptyView;
    private RecyclerView mRecView;
    private ListeningGestureDetector mGestureDetector;

    private String mStateKey;

    private int mLastSortOrder = SORT_ORDER_UNKNOWN;
    private DocumentsAdapter mAdapter;
    private FragmentTuner mTuner;
    private DocumentClipper mClipper;
    private GridLayoutManager mLayout;
    private int mColumnCount = 1;  // This will get updated when layout changes.

    private LayoutInflater mInflater;
    private MessageBar mMessageBar;
    private View mProgressBar;

    // Directory fragment state is defined by: root, document, query, type, selection
    private @ResultType int mType = TYPE_NORMAL;
    private RootInfo mRoot;
    private DocumentInfo mDocument;
    private String mQuery = null;
    // Note, we use !null to indicate that selection was restored (from rotation).
    // So don't fiddle with this field unless you've got the bigger picture in mind.
    private @Nullable Selection mRestoredSelection = null;
    // Here we save the clip details of moveTo/copyTo actions when picker shows up.
    // This will be written to saved instance.
    private @Nullable FileOperation mPendingOperation;
    private boolean mSearchMode = false;

    private @Nullable BandController mBandController;
    private @Nullable ActionMode mActionMode;

    private DragScrollListener mOnDragListener;
    private MenuManager mMenuManager;

    @Override
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mInflater = inflater;
        final View view = inflater.inflate(R.layout.fragment_directory, container, false);

        mMessageBar = MessageBar.create(getChildFragmentManager());
        mProgressBar = view.findViewById(R.id.progressbar);

        mRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.refresh_layout);
        mRefreshLayout.setOnRefreshListener(this);

        mEmptyView = view.findViewById(android.R.id.empty);
        mRecView = (RecyclerView) view.findViewById(R.id.dir_list);
        mRecView.setRecyclerListener(
                new RecyclerListener() {
                    @Override
                    public void onViewRecycled(ViewHolder holder) {
                        cancelThumbnailTask(holder.itemView);
                    }
                });

        mRecView.setItemAnimator(new DirectoryItemAnimator(getActivity()));

        final int edgeHeight = (int) getResources().getDimension(R.dimen.autoscroll_edge_height);
        mOnDragListener = DragScrollListener.create(
                edgeHeight, new DirectoryDragListener(this), mRecView);

        // Make the recycler and the empty views responsive to drop events.
        mRecView.setOnDragListener(mOnDragListener);
        mEmptyView.setOnDragListener(mOnDragListener);

        return view;
    }

    @Override
    public void onDestroyView() {
        mSelectionMgr.clearSelection();

        // Cancel any outstanding thumbnail requests
        final int count = mRecView.getChildCount();
        for (int i = 0; i < count; i++) {
            final View view = mRecView.getChildAt(i);
            cancelThumbnailTask(view);
        }

        super.onDestroyView();
    }

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

        final Context context = getActivity();
        final State state = getDisplayState();

        // Read arguments when object created for the first time.
        // Restore state if fragment recreated.
        Bundle args = savedInstanceState == null ? getArguments() : savedInstanceState;
        mRoot = args.getParcelable(Shared.EXTRA_ROOT);
        mDocument = args.getParcelable(Shared.EXTRA_DOC);
        mStateKey = buildStateKey(mRoot, mDocument);
        mQuery = args.getString(Shared.EXTRA_QUERY);
        mType = args.getInt(Shared.EXTRA_TYPE);
        mSearchMode = args.getBoolean(Shared.EXTRA_SEARCH_MODE);
        mPendingOperation = args.getParcelable(FileOperationService.EXTRA_OPERATION);

        // Restore any selection we may have squirreled away in retained state.
        @Nullable RetainedState retained = getBaseActivity().getRetainedState();
        if (retained != null && retained.hasSelection()) {
            // We claim the selection for ourselves and null it out once used
            // so we don't have a rando selection hanging around in RetainedState.
            mRestoredSelection = retained.selection;
            retained.selection = null;
        }

        mIconHelper = new IconHelper(context, MODE_GRID);

        mAdapter = new SectionBreakDocumentsAdapterWrapper(
                this, new ModelBackedDocumentsAdapter(this, mIconHelper));

        mRecView.setAdapter(mAdapter);

        mLayout = new GridLayoutManager(getContext(), mColumnCount);
        SpanSizeLookup lookup = mAdapter.createSpanSizeLookup();
        if (lookup != null) {
            mLayout.setSpanSizeLookup(lookup);
        }
        mRecView.setLayoutManager(mLayout);

        // TODO: instead of inserting the view into the constructor, extract listener-creation code
        // and set the listener on the view after the fact.  Then the view doesn't need to be passed
        // into the selection manager.
        mSelectionMgr = new MultiSelectManager(
                mAdapter,
                state.allowMultiple
                    ? MultiSelectManager.MODE_MULTIPLE
                    : MultiSelectManager.MODE_SINGLE);

        // Make sure this is done after the RecyclerView is set up.
        mFocusManager = new FocusManager(context, mRecView, mModel);

        mInputHandler = new UserInputHandler<>(
                mSelectionMgr,
                mFocusManager,
                new Function<MotionEvent, InputEvent>() {
                    @Override
                    public InputEvent apply(MotionEvent t) {
                        return MotionInputEvent.obtain(t, mRecView);
                    }
                },
                this::getTarget,
                this::canSelect,
                this::onRightClick,
                this::onActivate,
                (DocumentDetails ignored) -> {
                    return onDeleteSelectedDocuments();
                });

        mGestureDetector =
                new ListeningGestureDetector(this.getContext(), mDragHelper, mInputHandler);

        mRecView.addOnItemTouchListener(mGestureDetector);
        mEmptyView.setOnTouchListener(mGestureDetector);

        if (state.allowMultiple) {
            mBandController = new BandController(mRecView, mAdapter, mSelectionMgr);
        }

        mSelectionModeListener = new SelectionModeListener();
        mSelectionMgr.addCallback(mSelectionModeListener);

        mModel = new Model();
        mModel.addUpdateListener(mAdapter);
        mModel.addUpdateListener(mModelUpdateListener);

        final BaseActivity activity = getBaseActivity();
        mTuner = activity.createFragmentTuner();
        mMenuManager = activity.getMenuManager();
        mClipper = DocumentsApplication.getDocumentClipper(getContext());

        final ActivityManager am = (ActivityManager) context.getSystemService(
                Context.ACTIVITY_SERVICE);
        boolean svelte = am.isLowRamDevice() && (mType == TYPE_RECENT_OPEN);
        mIconHelper.setThumbnailsEnabled(!svelte);

        // Kick off loader at least once
        getLoaderManager().restartLoader(LOADER_ID, null, this);
    }

    public void retainState(RetainedState state) {
        state.selection = mSelectionMgr.getSelection(new Selection());
    }

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

        outState.putInt(Shared.EXTRA_TYPE, mType);
        outState.putParcelable(Shared.EXTRA_ROOT, mRoot);
        outState.putParcelable(Shared.EXTRA_DOC, mDocument);
        outState.putString(Shared.EXTRA_QUERY, mQuery);
        outState.putBoolean(Shared.EXTRA_SEARCH_MODE, mSearchMode);
        outState.putParcelable(FileOperationService.EXTRA_OPERATION, mPendingOperation);
    }

    @Override
    public void onActivityResult(@RequestCode int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_COPY_DESTINATION:
                handleCopyResult(resultCode, data);
                break;
            default:
                throw new UnsupportedOperationException("Unknown request code: " + requestCode);
        }
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu,
            View v,
            ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getActivity().getMenuInflater();
        inflater.inflate(R.menu.context_menu, menu);

        menu.add(Menu.NONE, R.id.menu_create_dir, Menu.NONE, R.string.menu_create_dir);
        menu.add(Menu.NONE, R.id.menu_delete, Menu.NONE, R.string.menu_delete);
        menu.add(Menu.NONE, R.id.menu_rename, Menu.NONE, R.string.menu_rename);

        if (v == mRecView || v == mEmptyView) {
            mMenuManager.updateContextMenu(menu, null, getBaseActivity().getDirectoryDetails());
        } else {
            mMenuManager.updateContextMenu(menu, mSelectionModeListener,
                    getBaseActivity().getDirectoryDetails());
        }
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        return handleMenuItemClick(item);
    }

    private void handleCopyResult(int resultCode, Intent data) {

        FileOperation operation = mPendingOperation;
        mPendingOperation = null;

        if (resultCode == Activity.RESULT_CANCELED || data == null) {
            // User pressed the back button or otherwise cancelled the destination pick. Don't
            // proceed with the copy.
            operation.dispose();
            return;
        }

        operation.setDestination(data.getParcelableExtra(Shared.EXTRA_STACK));

        BaseActivity activity = getBaseActivity();
        FileOperations.start(activity, operation, activity.fileOpCallback);
    }

    protected boolean onRightClick(InputEvent e) {
        if (e.getItemPosition() != RecyclerView.NO_POSITION) {
            final DocumentHolder doc = getTarget(e);
            if (!mSelectionMgr.getSelection().contains(doc.modelId)) {
                mSelectionMgr.replaceSelection(Collections.singleton(doc.modelId));
            }

            // We are registering for context menu here so long-press doesn't trigger this
            // floating context menu, and then quickly unregister right afterwards
            registerForContextMenu(doc.itemView);
            mRecView.showContextMenuForChild(doc.itemView,
                    e.getX() - doc.itemView.getLeft(), e.getY() - doc.itemView.getTop());
            unregisterForContextMenu(doc.itemView);
            return true;
        }

        // If there was no corresponding item pos, that means user right-clicked on the blank
        // pane
        // We would want to show different options then, and not select any item
        // The blank pane could be the recyclerView or the emptyView, so we need to register
        // according to whichever one is visible
        if (mEmptyView.getVisibility() == View.VISIBLE) {
            registerForContextMenu(mEmptyView);
            mEmptyView.showContextMenu(e.getX(), e.getY());
            unregisterForContextMenu(mEmptyView);
            return true;
        }

        registerForContextMenu(mRecView);
        mRecView.showContextMenu(e.getX(), e.getY());
        unregisterForContextMenu(mRecView);
        return true;
    }

    private boolean handleViewItem(String id) {
        final Cursor cursor = mModel.getItem(id);

        if (cursor == null) {
            Log.w(TAG, "Can't view item. Can't obtain cursor for modeId" + id);
            return false;
        }

        final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
        final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
        if (mTuner.isDocumentEnabled(docMimeType, docFlags)) {
            final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
            getBaseActivity().onDocumentPicked(doc, mModel);
            mSelectionMgr.clearSelection();
            return true;
        }
        return false;
    }

    @Override
    public void onStop() {
        super.onStop();

        // Remember last scroll location
        final SparseArray<Parcelable> container = new SparseArray<Parcelable>();
        getView().saveHierarchyState(container);
        final State state = getDisplayState();
        state.dirState.put(mStateKey, container);
    }

    public void onDisplayStateChanged() {
        updateDisplayState();
    }

    public void onSortOrderChanged() {
        // Sort order is implemented as a sorting wrapper around directory
        // results. So when sort order changes, we force a reload of the directory.
        getLoaderManager().restartLoader(LOADER_ID, null, this);
    }

    public void onViewModeChanged() {
        // Mode change is just visual change; no need to kick loader.
        updateDisplayState();
    }

    private void updateDisplayState() {
        State state = getDisplayState();
        updateLayout(state.derivedMode);
        mRecView.setAdapter(mAdapter);
    }

    /**
     * Updates the layout after the view mode switches.
     * @param mode The new view mode.
     */
    private void updateLayout(@ViewMode int mode) {
        mColumnCount = calculateColumnCount(mode);
        if (mLayout != null) {
            mLayout.setSpanCount(mColumnCount);
        }

        int pad = getDirectoryPadding(mode);
        mRecView.setPadding(pad, pad, pad, pad);
        mRecView.requestLayout();
        if (mBandController != null) {
            mBandController.handleLayoutChanged();
        }
        mIconHelper.setViewMode(mode);
    }

    private int calculateColumnCount(@ViewMode int mode) {
        if (mode == MODE_LIST) {
            // List mode is a "grid" with 1 column.
            return 1;
        }

        int cellWidth = getResources().getDimensionPixelSize(R.dimen.grid_width);
        int cellMargin = 2 * getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
        int viewPadding = mRecView.getPaddingLeft() + mRecView.getPaddingRight();

        // RecyclerView sometimes gets a width of 0 (see b/27150284).  Clamp so that we always lay
        // out the grid with at least 2 columns.
        int columnCount = Math.max(2,
                (mRecView.getWidth() - viewPadding) / (cellWidth + cellMargin));

        return columnCount;
    }

    private int getDirectoryPadding(@ViewMode int mode) {
        switch (mode) {
            case MODE_GRID:
                return getResources().getDimensionPixelSize(R.dimen.grid_container_padding);
            case MODE_LIST:
                return getResources().getDimensionPixelSize(R.dimen.list_container_padding);
            default:
                throw new IllegalArgumentException("Unsupported layout mode: " + mode);
        }
    }

    @Override
    public int getColumnCount() {
        return mColumnCount;
    }

    // Support method to replace getOwner().foo() with something
    // slightly less clumsy like: getOwner().foo().
    private BaseActivity getBaseActivity() {
        return (BaseActivity) getActivity();
    }

    /**
     * Manages the integration between our ActionMode and MultiSelectManager, initiating
     * ActionMode when there is a selection, canceling it when there is no selection,
     * and clearing selection when action mode is explicitly exited by the user.
     */
    private final class SelectionModeListener implements MultiSelectManager.Callback,
            ActionMode.Callback, MenuManager.SelectionDetails {

        private Selection mSelected = new Selection();

        // Partial files are files that haven't been fully downloaded.
        private int mPartialCount = 0;
        private int mDirectoryCount = 0;
        private int mNoDeleteCount = 0;
        private int mNoRenameCount = 0;

        private Menu mMenu;

        @Override
        public boolean onBeforeItemStateChange(String modelId, boolean selected) {
            if (selected) {
                final Cursor cursor = mModel.getItem(modelId);
                if (cursor == null) {
                    Log.w(TAG, "Can't obtain cursor for modelId: " + modelId);
                    return false;
                }

                final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
                final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
                if (!mTuner.canSelectType(docMimeType, docFlags)) {
                    return false;
                }
                return mTuner.canSelectType(docMimeType, docFlags);
            }
            return true;
        }

        @Override
        public void onItemStateChanged(String modelId, boolean selected) {
            final Cursor cursor = mModel.getItem(modelId);
            if (cursor == null) {
                Log.w(TAG, "Model returned null cursor for document: " + modelId
                        + ". Ignoring state changed event.");
                return;
            }

            // TODO: Should this be happening in onSelectionChanged? Technically this callback is
            // triggered on "silent" selection updates (i.e. we might be reacting to unfinalized
            // selection changes here)
            final String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
            if (MimePredicate.isDirectoryType(mimeType)) {
                mDirectoryCount += selected ? 1 : -1;
            }

            final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
            if ((docFlags & Document.FLAG_PARTIAL) != 0) {
                mPartialCount += selected ? 1 : -1;
            }
            if ((docFlags & Document.FLAG_SUPPORTS_DELETE) == 0) {
                mNoDeleteCount += selected ? 1 : -1;
            }
            if ((docFlags & Document.FLAG_SUPPORTS_RENAME) == 0) {
                mNoRenameCount += selected ? 1 : -1;
            }
        }

        @Override
        public void onSelectionChanged() {
            mSelectionMgr.getSelection(mSelected);
            if (mSelected.size() > 0) {
                if (DEBUG) Log.d(TAG, "Maybe starting action mode.");
                if (mActionMode == null) {
                    if (DEBUG) Log.d(TAG, "Yeah. Starting action mode.");
                    mActionMode = getActivity().startActionMode(this);
                }
                updateActionMenu();
            } else {
                if (DEBUG) Log.d(TAG, "Finishing action mode.");
                if (mActionMode != null) {
                    mActionMode.finish();
                }
            }

            if (mActionMode != null) {
                assert(!mSelected.isEmpty());
                final String title = Shared.getQuantityString(getActivity(),
                        R.plurals.elements_selected, mSelected.size());
                mActionMode.setTitle(title);
                mRecView.announceForAccessibility(title);
            }
        }

        // Called when the user exits the action mode
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            if (DEBUG) Log.d(TAG, "Handling action mode destroyed.");
            mActionMode = null;
            // clear selection
            mSelectionMgr.clearSelection();
            mSelected.clear();

            mDirectoryCount = 0;
            mPartialCount = 0;
            mNoDeleteCount = 0;
            mNoRenameCount = 0;

            // Re-enable TalkBack for the toolbars, as they are no longer covered by action mode.
            final Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
            toolbar.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);

            // This toolbar is not present in the fixed_layout
            final Toolbar rootsToolbar = (Toolbar) getActivity().findViewById(R.id.roots_toolbar);
            if (rootsToolbar != null) {
                rootsToolbar.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
            }
        }

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            if (mRestoredSelection != null) {
                // This is a careful little song and dance to avoid haptic feedback
                // when selection has been restored after rotation. We're
                // also responsible for cleaning up restored selection so the
                // object dones't unnecessarily hang around.
                mRestoredSelection = null;
            } else {
                mRecView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
            }

            int size = mSelectionMgr.getSelection().size();
            mode.getMenuInflater().inflate(R.menu.mode_directory, menu);
            mode.setTitle(TextUtils.formatSelectedCount(size));

            if (size > 0) {
                // Hide the toolbars if action mode is enabled, so TalkBack doesn't navigate to
                // these controls when using linear navigation.
                final Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
                toolbar.setImportantForAccessibility(
                        View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);

                // This toolbar is not present in the fixed_layout
                final Toolbar rootsToolbar = (Toolbar) getActivity().findViewById(
                        R.id.roots_toolbar);
                if (rootsToolbar != null) {
                    rootsToolbar.setImportantForAccessibility(
                            View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
                }
                return true;
            }

            return false;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            mMenu = menu;
            updateActionMenu();
            return true;
        }

        @Override
        public boolean containsDirectories() {
            return mDirectoryCount > 0;
        }

        @Override
        public boolean containsPartialFiles() {
            return mPartialCount > 0;
        }

        @Override
        public boolean canDelete() {
            return mNoDeleteCount == 0;
        }

        @Override
        public boolean canRename() {
            return mNoRenameCount == 0 && mSelectionMgr.getSelection().size() == 1;
        }

        private void updateActionMenu() {
            assert(mMenu != null);
            mMenuManager.updateActionMenu(mMenu, this);
            Menus.disableHiddenItems(mMenu);
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            return handleMenuItemClick(item);
        }
    }

    private boolean handleMenuItemClick(MenuItem item) {
        Selection selection = mSelectionMgr.getSelection(new Selection());

        switch (item.getItemId()) {
            case R.id.menu_open:
                openDocuments(selection);
                mActionMode.finish();
                return true;

            case R.id.menu_share:
                shareDocuments(selection);
                // TODO: Only finish selection if share action is completed.
                mActionMode.finish();
                return true;

            case R.id.menu_delete:
                // deleteDocuments will end action mode if the documents are deleted.
                // It won't end action mode if user cancels the delete.
                deleteDocuments(selection);
                return true;

            case R.id.menu_copy_to:
                transferDocuments(selection, FileOperationService.OPERATION_COPY);
                // TODO: Only finish selection mode if copy-to is not canceled.
                // Need to plum down into handling the way we do with deleteDocuments.
                mActionMode.finish();
                return true;

            case R.id.menu_move_to:
                // Exit selection mode first, so we avoid deselecting deleted documents.
                mActionMode.finish();
                transferDocuments(selection, FileOperationService.OPERATION_MOVE);
                return true;

            case R.id.menu_cut_to_clipboard:
                cutSelectedToClipboard();
                return true;

            case R.id.menu_copy_to_clipboard:
                copySelectedToClipboard();
                return true;

            case R.id.menu_paste_from_clipboard:
                pasteFromClipboard();
                return true;

            case R.id.menu_select_all:
                selectAllFiles();
                return true;

            case R.id.menu_rename:
                // Exit selection mode first, so we avoid deselecting deleted
                // (renamed) documents.
                mActionMode.finish();
                renameDocuments(selection);
                return true;

            default:
                // See if BaseActivity can handle this particular MenuItem
                if (!getBaseActivity().onOptionsItemSelected(item)) {
                    if (DEBUG) Log.d(TAG, "Unhandled menu item selected: " + item);
                    return false;
                }
                return true;
        }
    }

    public final boolean onBackPressed() {
        if (mSelectionMgr.hasSelection()) {
            if (DEBUG) Log.d(TAG, "Clearing selection on selection manager.");
            mSelectionMgr.clearSelection();
            return true;
        }
        return false;
    }

    private void cancelThumbnailTask(View view) {
        final ImageView iconThumb = (ImageView) view.findViewById(R.id.icon_thumb);
        if (iconThumb != null) {
            mIconHelper.stopLoading(iconThumb);
        }
    }

    private void openDocuments(final Selection selected) {
        Metrics.logUserAction(getContext(), Metrics.USER_ACTION_OPEN);

        new GetDocumentsTask() {
            @Override
            void onDocumentsReady(List<DocumentInfo> docs) {
                // TODO: Implement support in Files activity for opening multiple docs.
                BaseActivity.get(DirectoryFragment.this).onDocumentsPicked(docs);
            }
        }.execute(selected);
    }

    private void shareDocuments(final Selection selected) {
        Metrics.logUserAction(getContext(), Metrics.USER_ACTION_SHARE);

        new GetDocumentsTask() {
            @Override
            void onDocumentsReady(List<DocumentInfo> docs) {
                Intent intent;

                // Filter out directories and virtual files - those can't be shared.
                List<DocumentInfo> docsForSend = new ArrayList<>();
                for (DocumentInfo doc: docs) {
                    if (!doc.isDirectory() && !doc.isVirtualDocument()) {
                        docsForSend.add(doc);
                    }
                }

                if (docsForSend.size() == 1) {
                    final DocumentInfo doc = docsForSend.get(0);

                    intent = new Intent(Intent.ACTION_SEND);
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    intent.addCategory(Intent.CATEGORY_DEFAULT);
                    intent.setType(doc.mimeType);
                    intent.putExtra(Intent.EXTRA_STREAM, doc.derivedUri);

                } else if (docsForSend.size() > 1) {
                    intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    intent.addCategory(Intent.CATEGORY_DEFAULT);

                    final ArrayList<String> mimeTypes = new ArrayList<>();
                    final ArrayList<Uri> uris = new ArrayList<>();
                    for (DocumentInfo doc : docsForSend) {
                        mimeTypes.add(doc.mimeType);
                        uris.add(doc.derivedUri);
                    }

                    intent.setType(findCommonMimeType(mimeTypes));
                    intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);

                } else {
                    return;
                }

                intent = Intent.createChooser(intent, getActivity().getText(R.string.share_via));
                startActivity(intent);
            }
        }.execute(selected);
    }

    private String generateDeleteMessage(final List<DocumentInfo> docs) {
        String message;
        int dirsCount = 0;

        for (DocumentInfo doc : docs) {
            if (doc.isDirectory()) {
                ++dirsCount;
            }
        }

        if (docs.size() == 1) {
            // Deleteing 1 file xor 1 folder in cwd

            // Address b/28772371, where including user strings in message can result in
            // broken bidirectional support.
            String displayName = BidiFormatter.getInstance().unicodeWrap(docs.get(0).displayName);
            message = dirsCount == 0
                    ? getActivity().getString(R.string.delete_filename_confirmation_message,
                            displayName)
                    : getActivity().getString(R.string.delete_foldername_confirmation_message,
                            displayName);
        } else if (dirsCount == 0) {
            // Deleting only files in cwd
            message = Shared.getQuantityString(getActivity(),
                    R.plurals.delete_files_confirmation_message, docs.size());
        } else if (dirsCount == docs.size()) {
            // Deleting only folders in cwd
            message = Shared.getQuantityString(getActivity(),
                    R.plurals.delete_folders_confirmation_message, docs.size());
        } else {
            // Deleting mixed items (files and folders) in cwd
            message = Shared.getQuantityString(getActivity(),
                    R.plurals.delete_items_confirmation_message, docs.size());
        }
        return message;
    }

    private boolean onDeleteSelectedDocuments() {
        if (mSelectionMgr.hasSelection()) {
            deleteDocuments(mSelectionMgr.getSelection(new Selection()));
        }
        return false;
    }

    private boolean onActivate(DocumentDetails doc) {
        // Toggle selection if we're in selection mode, othewise, view item.
        if (mSelectionMgr.hasSelection()) {
            mSelectionMgr.toggleSelection(doc.getModelId());
        } else {
            handleViewItem(doc.getModelId());
        }
        return true;
    }

//    private boolean onSelect(DocumentDetails doc) {
//        mSelectionMgr.toggleSelection(doc.getModelId());
//        mSelectionMgr.setSelectionRangeBegin(doc.getAdapterPosition());
//        return true;
//    }

    private void deleteDocuments(final Selection selected) {
        Metrics.logUserAction(getContext(), Metrics.USER_ACTION_DELETE);

        assert(!selected.isEmpty());

        final DocumentInfo srcParent = getDisplayState().stack.peek();
        new GetDocumentsTask() {
            @Override
            void onDocumentsReady(final List<DocumentInfo> docs) {

                TextView message =
                        (TextView) mInflater.inflate(R.layout.dialog_delete_confirmation, null);
                message.setText(generateDeleteMessage(docs));

                // For now, we implement this dialog NOT
                // as a fragment (which can survive rotation and have its own state),
                // but as a simple runtime dialog. So rotating a device with an
                // active delete dialog...results in that dialog disappearing.
                // We can do better, but don't have cycles for it now.
                new AlertDialog.Builder(getActivity())
                    .setView(message)
                    .setPositiveButton(
                         android.R.string.ok,
                         new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int id) {
                                // Finish selection mode first which clears selection so we
                                // don't end up trying to deselect deleted documents.
                                // This is done here, rather in the onActionItemClicked
                                // so we can avoid de-selecting items in the case where
                                // the user cancels the delete.
                                if (mActionMode != null) {
                                    mActionMode.finish();
                                } else {
                                    Log.w(TAG, "Action mode is null before deleting documents.");
                                }

                                UrisSupplier srcs;
                                try {
                                    srcs = UrisSupplier.create(
                                            selected,
                                            mModel::getItemUri,
                                            getContext());
                                } catch(IOException e) {
                                    throw new RuntimeException("Failed to create uri supplier.", e);
                                }

                                FileOperation operation = new FileOperation.Builder()
                                        .withOpType(FileOperationService.OPERATION_DELETE)
                                        .withDestination(getDisplayState().stack)
                                        .withSrcs(srcs)
                                        .withSrcParent(srcParent.derivedUri)
                                        .build();

                                BaseActivity activity = getBaseActivity();
                                FileOperations.start(activity, operation, activity.fileOpCallback);
                            }
                        })
                    .setNegativeButton(android.R.string.cancel, null)
                    .show();
            }
        }.execute(selected);
    }

    private void transferDocuments(final Selection selected, final @OpType int mode) {
        if(mode == FileOperationService.OPERATION_COPY) {
            Metrics.logUserAction(getContext(), Metrics.USER_ACTION_COPY_TO);
        } else if (mode == FileOperationService.OPERATION_MOVE) {
            Metrics.logUserAction(getContext(), Metrics.USER_ACTION_MOVE_TO);
        }

        // Pop up a dialog to pick a destination.  This is inadequate but works for now.
        // TODO: Implement a picker that is to spec.
        final Intent intent = new Intent(
                Shared.ACTION_PICK_COPY_DESTINATION,
                Uri.EMPTY,
                getActivity(),
                DocumentsActivity.class);

        UrisSupplier srcs;
        try {
            srcs = UrisSupplier.create(selected, mModel::getItemUri, getContext());
        } catch(IOException e) {
            throw new RuntimeException("Failed to create uri supplier.", e);
        }

        Uri srcParent = getDisplayState().stack.peek().derivedUri;
        mPendingOperation = new FileOperation.Builder()
                .withOpType(mode)
                .withSrcParent(srcParent)
                .withSrcs(srcs)
                .build();

        // Relay any config overrides bits present in the original intent.
        Intent original = getActivity().getIntent();
        if (original != null && original.hasExtra(Shared.EXTRA_PRODUCTIVITY_MODE)) {
            intent.putExtra(
                    Shared.EXTRA_PRODUCTIVITY_MODE,
                    original.getBooleanExtra(Shared.EXTRA_PRODUCTIVITY_MODE, false));
        }

        // Set an appropriate title on the drawer when it is shown in the picker.
        // Coupled with the fact that we auto-open the drawer for copy/move operations
        // it should basically be the thing people see first.
        int drawerTitleId = mode == FileOperationService.OPERATION_MOVE
                ? R.string.menu_move : R.string.menu_copy;
        intent.putExtra(DocumentsContract.EXTRA_PROMPT, getResources().getString(drawerTitleId));

        new GetDocumentsTask() {
            @Override
            void onDocumentsReady(List<DocumentInfo> docs) {
                // Determine if there is a directory in the set of documents
                // to be copied? Why? Directory creation isn't supported by some roots
                // (like Downloads). This informs DocumentsActivity (the "picker")
                // to restrict available roots to just those with support.
                intent.putExtra(Shared.EXTRA_DIRECTORY_COPY, hasDirectory(docs));
                intent.putExtra(FileOperationService.EXTRA_OPERATION_TYPE, mode);

                // This just identifies the type of request...we'll check it
                // when we reveive a response.
                startActivityForResult(intent, REQUEST_COPY_DESTINATION);
            }

        }.execute(selected);
    }

    private static boolean hasDirectory(List<DocumentInfo> docs) {
        for (DocumentInfo info : docs) {
            if (Document.MIME_TYPE_DIR.equals(info.mimeType)) {
                return true;
            }
        }
        return false;
    }

    private void renameDocuments(Selection selected) {
        Metrics.logUserAction(getContext(), Metrics.USER_ACTION_RENAME);

        // Batch renaming not supported
        // Rename option is only available in menu when 1 document selected
        assert(selected.size() == 1);

        new GetDocumentsTask() {
            @Override
            void onDocumentsReady(List<DocumentInfo> docs) {
                RenameDocumentFragment.show(getFragmentManager(), docs.get(0));
            }
        }.execute(selected);
    }

    @Override
    public void initDocumentHolder(DocumentHolder holder) {
        holder.addKeyEventListener(mInputHandler);
        holder.itemView.setOnFocusChangeListener(mFocusManager);
    }

    @Override
    public void onBindDocumentHolder(DocumentHolder holder, Cursor cursor) {
        setupDragAndDropOnDocumentView(holder.itemView, cursor);
    }

    @Override
    public State getDisplayState() {
        return getBaseActivity().getDisplayState();
    }

    @Override
    public Model getModel() {
        return mModel;
    }

    @Override
    public boolean isDocumentEnabled(String docMimeType, int docFlags) {
        return mTuner.isDocumentEnabled(docMimeType, docFlags);
    }

    private void showEmptyDirectory() {
        showEmptyView(R.string.empty, R.drawable.cabinet);
    }

    private void showNoResults(RootInfo root) {
        CharSequence msg = getContext().getResources().getText(R.string.no_results);
        showEmptyView(String.format(String.valueOf(msg), root.title), R.drawable.cabinet);
    }

    private void showQueryError() {
        showEmptyView(R.string.query_error, R.drawable.hourglass);
    }

    private void showEmptyView(@StringRes int id, int drawable) {
        showEmptyView(getContext().getResources().getText(id), drawable);
    }

    private void showEmptyView(CharSequence msg, int drawable) {
        View content = mEmptyView.findViewById(R.id.content);
        TextView msgView = (TextView) mEmptyView.findViewById(R.id.message);
        ImageView imageView = (ImageView) mEmptyView.findViewById(R.id.artwork);
        msgView.setText(msg);
        imageView.setImageResource(drawable);

        mEmptyView.setVisibility(View.VISIBLE);
        mEmptyView.requestFocus();
        mRecView.setVisibility(View.GONE);
    }

    private void showDirectory() {
        mEmptyView.setVisibility(View.GONE);
        mRecView.setVisibility(View.VISIBLE);
        mRecView.requestFocus();
    }

    private String findCommonMimeType(List<String> mimeTypes) {
        String[] commonType = mimeTypes.get(0).split("/");
        if (commonType.length != 2) {
            return "*/*";
        }

        for (int i = 1; i < mimeTypes.size(); i++) {
            String[] type = mimeTypes.get(i).split("/");
            if (type.length != 2) continue;

            if (!commonType[1].equals(type[1])) {
                commonType[1] = "*";
            }

            if (!commonType[0].equals(type[0])) {
                commonType[0] = "*";
                commonType[1] = "*";
                break;
            }
        }

        return commonType[0] + "/" + commonType[1];
    }

    public void copySelectedToClipboard() {
        Metrics.logUserAction(getContext(), Metrics.USER_ACTION_COPY_CLIPBOARD);

        Selection selection = mSelectionMgr.getSelection(new Selection());
        if (selection.isEmpty()) {
            return;
        }
        mSelectionMgr.clearSelection();

        mClipper.clipDocumentsForCopy(mModel::getItemUri, selection);

        Snackbars.showDocumentsClipped(getActivity(), selection.size());
    }

    public void cutSelectedToClipboard() {
        Metrics.logUserAction(getContext(), Metrics.USER_ACTION_CUT_CLIPBOARD);

        Selection selection = mSelectionMgr.getSelection(new Selection());
        if (selection.isEmpty()) {
            return;
        }
        mSelectionMgr.clearSelection();

        mClipper.clipDocumentsForCut(mModel::getItemUri, selection, getDisplayState().stack.peek());

        Snackbars.showDocumentsClipped(getActivity(), selection.size());
    }

    public void pasteFromClipboard() {
        Metrics.logUserAction(getContext(), Metrics.USER_ACTION_PASTE_CLIPBOARD);

        BaseActivity activity = (BaseActivity) getActivity();
        DocumentInfo destination = activity.getCurrentDirectory();
        mClipper.copyFromClipboard(
                destination, activity.getDisplayState().stack, activity.fileOpCallback);
        getActivity().invalidateOptionsMenu();
    }

    public void selectAllFiles() {
        Metrics.logUserAction(getContext(), Metrics.USER_ACTION_SELECT_ALL);

        // Exclude disabled files
        List<String> enabled = new ArrayList<String>();
        for (String id : mAdapter.getModelIds()) {
            Cursor cursor = getModel().getItem(id);
            if (cursor == null) {
                Log.w(TAG, "Skipping selection. Can't obtain cursor for modeId: " + id);
                continue;
            }
            String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
            int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
            if (isDocumentEnabled(docMimeType, docFlags)) {
                enabled.add(id);
            }
        }

        // Only select things currently visible in the adapter.
        boolean changed = mSelectionMgr.setItemsSelected(enabled, true);
        if (changed) {
            updateDisplayState();
        }
    }

    /**
     * Attempts to restore focus on the directory listing.
     */
    public void requestFocus() {
        mFocusManager.restoreLastFocus();
    }

    private void setupDragAndDropOnDocumentView(View view, Cursor cursor) {
        final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
        if (Document.MIME_TYPE_DIR.equals(docMimeType)) {
            // Make a directory item a drop target. Drop on non-directories and empty space
            // is handled at the list/grid view level.
            view.setOnDragListener(mOnDragListener);
        }

        if (mTuner.dragAndDropEnabled()) {
            // Make all items draggable.
            view.setOnLongClickListener(onLongClickListener);
        }
    }

    void dragStarted() {
        // When files are selected for dragging, ActionMode is started. This obscures the breadcrumb
        // with an ActionBar. In order to make drag and drop to the breadcrumb possible, we first
        // end ActionMode so the breadcrumb is visible to the user.
        if (mActionMode != null) {
            mActionMode.finish();
        }
    }

    void dragStopped(boolean result) {
        if (result) {
            mSelectionMgr.clearSelection();
        }
    }

    @Override
    public void runOnUiThread(Runnable runnable) {
        getActivity().runOnUiThread(runnable);
    }

    /**
     * {@inheritDoc}
     *
     * In DirectoryFragment, we spring loads the hovered folder.
     */
    @Override
    public void onViewHovered(View view) {
        BaseActivity activity = (BaseActivity) getActivity();
        if (getModelId(view) != null) {
           activity.springOpenDirectory(getDestination(view));
        }

        activity.setRootsDrawerOpen(false);
    }

    boolean handleDropEvent(View v, DragEvent event) {
        BaseActivity activity = (BaseActivity) getActivity();
        activity.setRootsDrawerOpen(false);

        ClipData clipData = event.getClipData();
        assert (clipData != null);

        assert(DocumentClipper.getOpType(clipData) == FileOperationService.OPERATION_COPY);

        // Don't copy from the cwd into the cwd. Note: this currently doesn't work for
        // multi-window drag, because localState isn't carried over from one process to
        // another.
        Object src = event.getLocalState();
        DocumentInfo dst = getDestination(v);
        if (Objects.equals(src, dst)) {
            if (DEBUG) Log.d(TAG, "Drop target same as source. Ignoring.");
            return false;
        }

        // Recognize multi-window drag and drop based on the fact that localState is not
        // carried between processes. It will stop working when the localsState behavior
        // is changed. The info about window should be passed in the localState then.
        // The localState could also be null for copying from Recents in single window
        // mode, but Recents doesn't offer this functionality (no directories).
        Metrics.logUserAction(getContext(),
                src == null ? Metrics.USER_ACTION_DRAG_N_DROP_MULTI_WINDOW
                        : Metrics.USER_ACTION_DRAG_N_DROP);

        mClipper.copyFromClipData(dst, getDisplayState().stack, clipData, activity.fileOpCallback);
        return true;
    }

    private DocumentInfo getDestination(View v) {
        String id = getModelId(v);
        if (id != null) {
            Cursor dstCursor = mModel.getItem(id);
            if (dstCursor == null) {
                Log.w(TAG, "Invalid destination. Can't obtain cursor for modelId: " + id);
                return null;
            }
            return DocumentInfo.fromDirectoryCursor(dstCursor);
        }

        if (v == mRecView || v == mEmptyView) {
            return getDisplayState().stack.peek();
        }

        return null;
    }

    @Override
    public void setDropTargetHighlight(View v, boolean highlight) {
        // Note: use exact comparison - this code is searching for views which are children of
        // the RecyclerView instance in the UI.
        if (v.getParent() == mRecView) {
            RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(v);
            if (vh instanceof DocumentHolder) {
                ((DocumentHolder) vh).setHighlighted(highlight);
            }
        }
    }

    private @Nullable DocumentHolder getTarget(InputEvent e) {
        View childView = mRecView.findChildViewUnder(e.getX(), e.getY());
        if (childView != null) {
            return (DocumentHolder) mRecView.getChildViewHolder(childView);
        } else {
            return null;
        }
    }

    /**
     * Gets the model ID for a given RecyclerView item.
     * @param view A View that is a document item view, or a child of a document item view.
     * @return The Model ID for the given document, or null if the given view is not associated with
     *     a document item view.
     */
    protected @Nullable String getModelId(View view) {
        View itemView = mRecView.findContainingItemView(view);
        if (itemView != null) {
            RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(itemView);
            if (vh instanceof DocumentHolder) {
                return ((DocumentHolder) vh).modelId;
            }
        }
        return null;
    }

    /**
     * Abstract task providing support for loading documents *off*
     * the main thread. And if it isn't obvious, creating a list
     * of documents (especially large lists) can be pretty expensive.
     */
    private abstract class GetDocumentsTask
            extends AsyncTask<Selection, Void, List<DocumentInfo>> {
        @Override
        protected final List<DocumentInfo> doInBackground(Selection... selected) {
            return mModel.getDocuments(selected[0]);
        }

        @Override
        protected final void onPostExecute(List<DocumentInfo> docs) {
            onDocumentsReady(docs);
        }

        abstract void onDocumentsReady(List<DocumentInfo> docs);
    }

    @Override
    public boolean isSelected(String modelId) {
        return mSelectionMgr.getSelection().contains(modelId);
    }

    private final class ModelUpdateListener implements Model.UpdateListener {
        @Override
        public void onModelUpdate(Model model) {
            if (model.info != null || model.error != null) {
                mMessageBar.setInfo(model.info);
                mMessageBar.setError(model.error);
                mMessageBar.show();
            }

            mProgressBar.setVisibility(model.isLoading() ? View.VISIBLE : View.GONE);

            if (model.isEmpty()) {
                if (mSearchMode) {
                    showNoResults(getDisplayState().stack.root);
                } else {
                    showEmptyDirectory();
                }
            } else {
                showDirectory();
                mAdapter.notifyDataSetChanged();
            }

            if (!model.isLoading()) {
                getBaseActivity().notifyDirectoryLoaded(
                    model.doc != null ? model.doc.derivedUri : null);
            }
        }

        @Override
        public void onModelUpdateFailed(Exception e) {
            showQueryError();
        }
    }

    private Drawable getDragIcon(Selection selection) {
        if (selection.size() == 1) {
            DocumentInfo doc = getSingleSelectedDocument(selection);
            return mIconHelper.getDocumentIcon(getContext(), doc);
        }
        return getContext().getDrawable(com.android.internal.R.drawable.ic_doc_generic);
    }

    private String getDragTitle(Selection selection) {
        assert (!selection.isEmpty());
        if (selection.size() == 1) {
            DocumentInfo doc = getSingleSelectedDocument(selection);
            return doc.displayName;
        }

        return Shared.getQuantityString(getContext(), R.plurals.elements_dragged, selection.size());
    }

    private DocumentInfo getSingleSelectedDocument(Selection selection) {
        assert (selection.size() == 1);
        final List<DocumentInfo> docs = mModel.getDocuments(mSelectionMgr.getSelection());
        assert (docs.size() == 1);
        return docs.get(0);
    }

    private DragStartHelper.OnDragStartListener mOnDragStartListener =
            new DragStartHelper.OnDragStartListener() {
                @Override
                public boolean onDragStart(View v, DragStartHelper helper) {
                    Selection selection = mSelectionMgr.getSelection();

                    if (v == null) {
                        Log.d(TAG, "Ignoring drag event, null view");
                        return false;
                    }
                    if (!isSelected(getModelId(v))) {
                        Log.d(TAG, "Ignoring drag event, unselected view.");
                        return false;
                    }

                    // NOTE: Preparation of the ClipData object can require a lot of time
                    // and ideally should be done in the background. Unfortunately
                    // the current code layout and framework assumptions don't support
                    // this. So for now, we could end up doing a bunch of i/o on main thread.
                    v.startDragAndDrop(
                            mClipper.getClipDataForDocuments(
                                    mModel::getItemUri,
                                    selection,
                                    FileOperationService.OPERATION_COPY),
                            new DragShadowBuilder(
                                    getActivity(),
                                    getDragTitle(selection),
                                    getDragIcon(selection)),
                            getDisplayState().stack.peek(),
                            View.DRAG_FLAG_GLOBAL
                                    | View.DRAG_FLAG_GLOBAL_URI_READ
                                    | View.DRAG_FLAG_GLOBAL_URI_WRITE);

                    return true;
                }
            };


    private DragStartHelper mDragHelper = new DragStartHelper(null, mOnDragStartListener);

    private View.OnLongClickListener onLongClickListener = new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            return mDragHelper.onLongClick(v);
        }
    };

    private boolean canSelect(DocumentDetails doc) {
        return canSelect(doc.getModelId());
    }

    private boolean canSelect(String modelId) {

        // TODO: Combine this method with onBeforeItemStateChange, as both of them are almost
        // the same, and responsible for the same thing (whether to select or not).
        final Cursor cursor = mModel.getItem(modelId);
        if (cursor == null) {
            Log.w(TAG, "Couldn't obtain cursor for modelId: " + modelId);
            return false;
        }

        final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
        final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
        return mTuner.canSelectType(docMimeType, docFlags);
    }

    public static void showDirectory(
            FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) {
        create(fm, TYPE_NORMAL, root, doc, null, anim);
    }

    public static void showRecentsOpen(FragmentManager fm, int anim) {
        create(fm, TYPE_RECENT_OPEN, null, null, null, anim);
    }

    public static void reloadSearch(FragmentManager fm, RootInfo root, DocumentInfo doc,
            String query) {
        DirectoryFragment df = get(fm);

        df.mQuery = query;
        df.mRoot = root;
        df.mDocument = doc;
        df.mSearchMode =  query != null;
        df.getLoaderManager().restartLoader(LOADER_ID, null, df);
    }

    public static void reload(FragmentManager fm, int type, RootInfo root, DocumentInfo doc,
            String query) {
        DirectoryFragment df = get(fm);
        df.mType = type;
        df.mQuery = query;
        df.mRoot = root;
        df.mDocument = doc;
        df.mSearchMode =  query != null;
        df.getLoaderManager().restartLoader(LOADER_ID, null, df);
    }

    public static void create(FragmentManager fm, int type, RootInfo root, DocumentInfo doc,
            String query, int anim) {
        final Bundle args = new Bundle();
        args.putInt(Shared.EXTRA_TYPE, type);
        args.putParcelable(Shared.EXTRA_ROOT, root);
        args.putParcelable(Shared.EXTRA_DOC, doc);
        args.putString(Shared.EXTRA_QUERY, query);
        args.putParcelable(Shared.EXTRA_SELECTION, new Selection());

        final FragmentTransaction ft = fm.beginTransaction();
        AnimationView.setupAnimations(ft, anim, args);

        final DirectoryFragment fragment = new DirectoryFragment();
        fragment.setArguments(args);

        ft.replace(getFragmentId(), fragment);
        ft.commitAllowingStateLoss();
    }

    private static String buildStateKey(RootInfo root, DocumentInfo doc) {
        final StringBuilder builder = new StringBuilder();
        builder.append(root != null ? root.authority : "null").append(';');
        builder.append(root != null ? root.rootId : "null").append(';');
        builder.append(doc != null ? doc.documentId : "null");
        return builder.toString();
    }

    public static @Nullable DirectoryFragment get(FragmentManager fm) {
        // TODO: deal with multiple directories shown at once
        Fragment fragment = fm.findFragmentById(getFragmentId());
        return fragment instanceof DirectoryFragment
                ? (DirectoryFragment) fragment
                : null;
    }

    private static int getFragmentId() {
        return R.id.container_directory;
    }

    @Override
    public void onRefresh() {
        // Remove thumbnail cache. We do this not because we're worried about stale thumbnails as it
        // should be covered by last modified value we store in thumbnail cache, but rather to give
        // the user a greater sense that contents are being reloaded.
        ThumbnailCache cache = DocumentsApplication.getThumbnailCache(getContext());
        String[] ids = mModel.getModelIds();
        int numOfEvicts = Math.min(ids.length, CACHE_EVICT_LIMIT);
        for (int i = 0; i < numOfEvicts; ++i) {
            cache.removeUri(mModel.getItemUri(ids[i]));
        }

        // Trigger loading
        getLoaderManager().restartLoader(LOADER_ID, null, this);
    }

    @Override
    public Loader<DirectoryResult> onCreateLoader(int id, Bundle args) {
        Context context = getActivity();
        State state = getDisplayState();

        Uri contentsUri;
        switch (mType) {
            case TYPE_NORMAL:
                contentsUri = mSearchMode ? DocumentsContract.buildSearchDocumentsUri(
                        mRoot.authority, mRoot.rootId, mQuery)
                        : DocumentsContract.buildChildDocumentsUri(
                                mDocument.authority, mDocument.documentId);
                if (mTuner.managedModeEnabled()) {
                    contentsUri = DocumentsContract.setManageMode(contentsUri);
                }
                return new DirectoryLoader(
                        context, mType, mRoot, mDocument, contentsUri, state.userSortOrder,
                        mSearchMode);
            case TYPE_RECENT_OPEN:
                final RootsCache roots = DocumentsApplication.getRootsCache(context);
                return new RecentsLoader(context, roots, state);

            default:
                throw new IllegalStateException("Unknown type " + mType);
        }
    }

    @Override
    public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) {
        if (!isAdded()) return;

        if (mSearchMode) {
            Metrics.logUserAction(getContext(), Metrics.USER_ACTION_SEARCH);
        }

        State state = getDisplayState();

        mAdapter.notifyDataSetChanged();
        mModel.update(result);

        state.derivedSortOrder = result.sortOrder;

        updateLayout(state.derivedMode);

        if (mRestoredSelection != null) {
            mSelectionMgr.restoreSelection(mRestoredSelection);
            // Note, we'll take care of cleaning up retained selection
            // in the selection handler where we already have some
            // specialized code to handle when selection was restored.
        }

        // Restore any previous instance state
        final SparseArray<Parcelable> container = state.dirState.remove(mStateKey);
        if (container != null && !getArguments().getBoolean(Shared.EXTRA_IGNORE_STATE, false)) {
            getView().restoreHierarchyState(container);
        } else if (mLastSortOrder != state.derivedSortOrder) {
            // The derived sort order takes the user sort order into account, but applies
            // directory-specific defaults when the user doesn't explicitly set the sort
            // order. Scroll to the top if the sort order actually changed.
            mRecView.smoothScrollToPosition(0);
        }

        mLastSortOrder = state.derivedSortOrder;

        mTuner.onModelLoaded(mModel, mType, mSearchMode);

        if (mRefreshLayout.isRefreshing()) {
            new Handler().postDelayed(
                    () -> mRefreshLayout.setRefreshing(false),
                    REFRESH_SPINNER_DISMISS_DELAY);
        }
    }

    @Override
    public void onLoaderReset(Loader<DirectoryResult> loader) {
        mModel.update(null);

        mRefreshLayout.setRefreshing(false);
    }
  }
