/*
 * Copyright (C) 2016 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;

import android.view.KeyboardShortcutGroup;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;

import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;

import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.Menus;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.DirectoryFragment;
import com.android.documentsui.queries.SearchViewManager;
import com.android.documentsui.sidebar.RootsFragment;

import java.util.List;
import java.util.function.IntFunction;
import java.util.function.IntSupplier;

public abstract class MenuManager {
    private final static String TAG = "MenuManager";

    protected final SearchViewManager mSearchManager;
    protected final State mState;
    protected final DirectoryDetails mDirDetails;
    protected final IntSupplier mFilesCountSupplier;

    protected Menu mOptionMenu;

    public MenuManager(
            SearchViewManager searchManager,
            State displayState,
            DirectoryDetails dirDetails,
            IntSupplier filesCountSupplier) {
        mSearchManager = searchManager;
        mState = displayState;
        mDirDetails = dirDetails;
        mFilesCountSupplier = filesCountSupplier;
    }

    /** @see ActionModeController */
    public void updateActionMenu(Menu menu, SelectionDetails selection) {
        updateOpenWith(menu.findItem(R.id.action_menu_open_with), selection);
        updateDelete(menu.findItem(R.id.action_menu_delete), selection);
        updateShare(menu.findItem(R.id.action_menu_share), selection);
        updateRename(menu.findItem(R.id.action_menu_rename), selection);
        updateSelect(menu.findItem(R.id.action_menu_select), selection);
        updateSelectAll(menu.findItem(R.id.action_menu_select_all), selection);
        updateDeselectAll(menu.findItem(R.id.action_menu_deselect_all), selection);
        updateMoveTo(menu.findItem(R.id.action_menu_move_to), selection);
        updateCopyTo(menu.findItem(R.id.action_menu_copy_to), selection);
        updateCompress(menu.findItem(R.id.action_menu_compress), selection);
        updateExtractTo(menu.findItem(R.id.action_menu_extract_to), selection);
        updateInspect(menu.findItem(R.id.action_menu_inspect), selection);
        updateViewInOwner(menu.findItem(R.id.action_menu_view_in_owner), selection);
        updateSort(menu.findItem(R.id.action_menu_sort));

        Menus.disableHiddenItems(menu);
    }

    /** @see BaseActivity#onPrepareOptionsMenu */
    public void updateOptionMenu(Menu menu) {
        mOptionMenu = menu;
        updateOptionMenu();
    }

    public void updateOptionMenu() {
        if (mOptionMenu == null) {
            return;
        }
        updateCreateDir(mOptionMenu.findItem(R.id.option_menu_create_dir));
        updateSettings(mOptionMenu.findItem(R.id.option_menu_settings));
        updateSelectAll(mOptionMenu.findItem(R.id.option_menu_select_all));
        updateNewWindow(mOptionMenu.findItem(R.id.option_menu_new_window));
        updateAdvanced(mOptionMenu.findItem(R.id.option_menu_advanced));
        updateDebug(mOptionMenu.findItem(R.id.option_menu_debug));
        updateInspect(mOptionMenu.findItem(R.id.option_menu_inspect));
        updateSort(mOptionMenu.findItem(R.id.option_menu_sort));
        updateLauncher(mOptionMenu.findItem(R.id.option_menu_launcher));

        Menus.disableHiddenItems(mOptionMenu);
        mSearchManager.updateMenu();
    }

    public void updateSubMenu(Menu menu) {
        updateModePicker(menu.findItem(R.id.sub_menu_grid), menu.findItem(R.id.sub_menu_list));
    }

    public void updateModel(Model model) {}

    /**
     * Called when we needs {@link MenuManager} to ask Android to show context menu for us.
     * {@link MenuManager} can choose to defeat this request.
     *
     * {@link #inflateContextMenuForDocs} and {@link #inflateContextMenuForContainer} are called
     * afterwards when Android asks us to provide the content of context menus, so they're not
     * correct locations to suppress context menus.
     */
    public void showContextMenu(Fragment f, View v, float x, float y) {
        // Pickers don't have any context menu at this moment.
    }

    /**
     * Called when container context menu needs to be inflated.
     *
     * @param menu context menu from activity or fragment
     * @param inflater the MenuInflater
     * @param selectionDetails selection of files
     */
    public void inflateContextMenuForContainer(
            Menu menu, MenuInflater inflater, SelectionDetails selectionDetails) {
        throw new UnsupportedOperationException("Pickers don't allow context menu.");
    }

    public void inflateContextMenuForDocs(
            Menu menu, MenuInflater inflater, SelectionDetails selectionDetails) {
        throw new UnsupportedOperationException("Pickers don't allow context menu.");
    }

    /**
     * @see DirectoryFragment#onCreateContextMenu
     *
     * Called when user tries to generate a context menu anchored to a file when the selection
     * doesn't contain any folder.
     *
     * @param selectionDetails
     *      containsFiles may return false because this may be called when user right clicks on an
     *      unselectable item in pickers
     */
    @VisibleForTesting
    public void updateContextMenuForFiles(Menu menu, SelectionDetails selectionDetails) {
        assert selectionDetails != null;

        MenuItem share = menu.findItem(R.id.dir_menu_share);
        MenuItem open = menu.findItem(R.id.dir_menu_open);
        MenuItem openWith = menu.findItem(R.id.dir_menu_open_with);
        MenuItem rename = menu.findItem(R.id.dir_menu_rename);
        MenuItem viewInOwner = menu.findItem(R.id.dir_menu_view_in_owner);

        updateShare(share, selectionDetails);
        updateOpenInContextMenu(open, selectionDetails);
        updateOpenWith(openWith, selectionDetails);
        updateRename(rename, selectionDetails);
        updateViewInOwner(viewInOwner, selectionDetails);

        updateContextMenu(menu, selectionDetails);
    }

    /**
     * @see DirectoryFragment#onCreateContextMenu
     *
     * Called when user tries to generate a context menu anchored to a folder when the selection
     * doesn't contain any file.
     *
     * @param selectionDetails
     *      containDirectories may return false because this may be called when user right clicks on
     *      an unselectable item in pickers
     */
    @VisibleForTesting
    public void updateContextMenuForDirs(Menu menu, SelectionDetails selectionDetails) {
        assert selectionDetails != null;

        MenuItem openInNewWindow = menu.findItem(R.id.dir_menu_open_in_new_window);
        MenuItem rename = menu.findItem(R.id.dir_menu_rename);
        MenuItem pasteInto = menu.findItem(R.id.dir_menu_paste_into_folder);

        updateOpenInNewWindow(openInNewWindow, selectionDetails);
        updateRename(rename, selectionDetails);
        updatePasteInto(pasteInto, selectionDetails);

        updateContextMenu(menu, selectionDetails);
    }

    /**
     * @see DirectoryFragment#onCreateContextMenu
     *
     * Update shared context menu items of both files and folders context menus.
     */
    @VisibleForTesting
    public void updateContextMenu(Menu menu, SelectionDetails selectionDetails) {
        assert selectionDetails != null;

        MenuItem cut = menu.findItem(R.id.dir_menu_cut_to_clipboard);
        MenuItem copy = menu.findItem(R.id.dir_menu_copy_to_clipboard);
        MenuItem delete = menu.findItem(R.id.dir_menu_delete);
        MenuItem inspect = menu.findItem(R.id.dir_menu_inspect);

        final boolean canCopy =
                selectionDetails.size() > 0 && !selectionDetails.containsPartialFiles();
        final boolean canDelete = selectionDetails.canDelete();
        cut.setEnabled(canCopy && canDelete);
        copy.setEnabled(canCopy);
        delete.setEnabled(canDelete);

        inspect.setEnabled(selectionDetails.size() == 1);
    }

    /**
     * @see DirectoryFragment#onCreateContextMenu
     *
     * Called when user tries to generate a context menu anchored to an empty pane.
     */
    @VisibleForTesting
    public void updateContextMenuForContainer(Menu menu, SelectionDetails selectionDetails) {
        MenuItem paste = menu.findItem(R.id.dir_menu_paste_from_clipboard);
        MenuItem selectAll = menu.findItem(R.id.dir_menu_select_all);
        MenuItem deselectAll = menu.findItem(R.id.dir_menu_deselect_all);
        MenuItem createDir = menu.findItem(R.id.dir_menu_create_dir);
        MenuItem inspect = menu.findItem(R.id.dir_menu_inspect);

        paste.setEnabled(mDirDetails.hasItemsToPaste() && mDirDetails.canCreateDoc());
        updateSelectAll(selectAll, selectionDetails);
        updateDeselectAll(deselectAll, selectionDetails);
        updateCreateDir(createDir);
        updateInspect(inspect);
    }

    /**
     * @see RootsFragment#onCreateContextMenu
     */
    public void updateRootContextMenu(Menu menu, RootInfo root, DocumentInfo docInfo) {
        MenuItem eject = menu.findItem(R.id.root_menu_eject_root);
        MenuItem pasteInto = menu.findItem(R.id.root_menu_paste_into_folder);
        MenuItem openInNewWindow = menu.findItem(R.id.root_menu_open_in_new_window);
        MenuItem settings = menu.findItem(R.id.root_menu_settings);

        updateEject(eject, root);
        updatePasteInto(pasteInto, root, docInfo);
        updateOpenInNewWindow(openInNewWindow, root);
        updateSettings(settings, root);
    }

    public abstract void updateKeyboardShortcutsMenu(
            List<KeyboardShortcutGroup> data, IntFunction<String> stringSupplier);

    protected void updateModePicker(MenuItem grid, MenuItem list) {
        grid.setVisible(mState.derivedMode != State.MODE_GRID);
        list.setVisible(mState.derivedMode != State.MODE_LIST);
    }

    protected void updateAdvanced(MenuItem advanced) {
        advanced.setVisible(mState.showDeviceStorageOption);
        advanced.setTitle(mState.showDeviceStorageOption && mState.showAdvanced
                ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
    }

    protected void updateSort(MenuItem sort) {
        sort.setVisible(true);
    }

    protected void updateDebug(MenuItem debug) {
        debug.setVisible(mState.debugMode);
    }

    protected void updateSettings(MenuItem settings) {
        settings.setVisible(false);
    }

    protected void updateSettings(MenuItem settings, RootInfo root) {
        settings.setVisible(false);
    }

    protected void updateEject(MenuItem eject, RootInfo root) {
        eject.setVisible(false);
    }

    protected void updateNewWindow(MenuItem newWindow) {
        newWindow.setVisible(false);
    }

    protected void updateSelect(MenuItem select, SelectionDetails selectionDetails) {
        select.setVisible(false);
    }

    protected void updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails) {
        openWith.setVisible(false);
    }

    protected void updateOpenInNewWindow(
            MenuItem openInNewWindow, SelectionDetails selectionDetails) {
        openInNewWindow.setVisible(false);
    }

    protected void updateOpenInNewWindow(
            MenuItem openInNewWindow, RootInfo root) {
        openInNewWindow.setVisible(false);
    }

    protected void updateShare(MenuItem share, SelectionDetails selectionDetails) {
        share.setVisible(false);
    }

    protected void updateDelete(MenuItem delete, SelectionDetails selectionDetails) {
        delete.setVisible(false);
    }

    protected void updateRename(MenuItem rename, SelectionDetails selectionDetails) {
        rename.setVisible(false);
    }

    /**
     * This method is called for standard activity option menu as opposed
     * to when there is a selection.
     */
    protected void updateInspect(MenuItem inspector) {
        inspector.setVisible(false);
    }

    /**
     * This method is called for action mode, when a selection exists.
     */
    protected void updateInspect(MenuItem inspect, SelectionDetails selectionDetails) {
        inspect.setVisible(false);
    }

    protected void updateViewInOwner(MenuItem view, SelectionDetails selectionDetails) {
        view.setVisible(false);
    }

    protected void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails) {
        moveTo.setVisible(false);
    }

    protected void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails) {
        copyTo.setVisible(false);
    }

    protected void updateCompress(MenuItem compress, SelectionDetails selectionDetails) {
        compress.setVisible(false);
    }

    protected void updateExtractTo(MenuItem extractTo, SelectionDetails selectionDetails) {
        extractTo.setVisible(false);
    }

    protected void updatePasteInto(MenuItem pasteInto, SelectionDetails selectionDetails) {
        pasteInto.setVisible(false);
    }

    protected void updatePasteInto(MenuItem pasteInto, RootInfo root, DocumentInfo docInfo) {
        pasteInto.setVisible(false);
    }

    protected void updateOpenInContextMenu(MenuItem open, SelectionDetails selectionDetails) {
        open.setVisible(false);
    }

    protected void updateLauncher(MenuItem launcher) {
        launcher.setVisible(false);
    }

    protected abstract void updateSelectAll(MenuItem selectAll);
    protected abstract void updateSelectAll(MenuItem selectAll, SelectionDetails selectionDetails);
    protected abstract void updateDeselectAll(
            MenuItem deselectAll, SelectionDetails selectionDetails);
    protected abstract void updateCreateDir(MenuItem createDir);

    /**
     * Access to meta data about the selection.
     */
    public interface SelectionDetails {
        boolean containsDirectories();

        boolean containsFiles();

        int size();

        boolean containsPartialFiles();

        boolean containsFilesInArchive();

        // TODO: Update these to express characteristics instead of answering concrete questions,
        // since the answer to those questions is (or can be) activity specific.
        boolean canDelete();

        boolean canRename();

        boolean canPasteInto();

        boolean canExtract();

        boolean canOpenWith();

        boolean canViewInOwner();
    }

    public static class DirectoryDetails {
        private final BaseActivity mActivity;

        public DirectoryDetails(BaseActivity activity) {
            mActivity = activity;
        }

        public boolean hasRootSettings() {
            return mActivity.getCurrentRoot().hasSettings();
        }

        public boolean hasItemsToPaste() {
            return false;
        }

        public boolean canCreateDoc() {
            return isInRecents() ? false : mActivity.getCurrentDirectory().isCreateSupported();
        }

        public boolean isInRecents() {
            return mActivity.isInRecents();
        }

        public boolean canCreateDirectory() {
            return mActivity.canCreateDirectory();
        }

        public boolean canInspectDirectory() {
            return mActivity.canInspectDirectory() && !isInRecents();
        }
    }
}
