/*
 * Copyright (C) 2021 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.providers.media.photopicker;

import static android.content.Intent.ACTION_GET_CONTENT;
import static android.provider.MediaStore.ACTION_PICK_IMAGES;
import static android.provider.MediaStore.ACTION_USER_SELECT_IMAGES_FOR_APP;
import static android.provider.MediaStore.grantMediaReadForPackage;

import static com.android.providers.media.photopicker.PhotoPickerSettingsActivity.EXTRA_CURRENT_USER_ID;
import static com.android.providers.media.photopicker.data.PickerResult.getPickerResponseIntent;
import static com.android.providers.media.photopicker.data.PickerResult.getPickerUrisForItems;
import static com.android.providers.media.photopicker.util.LayoutModeUtils.MODE_PHOTOS_TAB;

import android.annotation.UserIdInt;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.MediaStore;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.WindowInsetsController;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.widget.TextView;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;

import com.android.providers.media.ConfigStore;
import com.android.providers.media.R;
import com.android.providers.media.photopicker.data.PickerResult;
import com.android.providers.media.photopicker.data.Selection;
import com.android.providers.media.photopicker.data.UserIdManager;
import com.android.providers.media.photopicker.data.model.Item;
import com.android.providers.media.photopicker.data.model.UserId;
import com.android.providers.media.photopicker.ui.TabContainerFragment;
import com.android.providers.media.photopicker.util.LayoutModeUtils;
import com.android.providers.media.photopicker.util.MimeFilterUtils;
import com.android.providers.media.photopicker.viewmodel.PickerViewModel;
import com.android.providers.media.util.ForegroundThread;

import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback;
import com.google.android.material.tabs.TabLayout;
import com.google.common.collect.Lists;

import java.util.List;

/**
 * Photo Picker allows users to choose one or more photos and/or videos to share with an app. The
 * app does not get access to all photos/videos.
 */
public class PhotoPickerActivity extends AppCompatActivity {
    private static final String TAG =  "PhotoPickerActivity";
    private static final float BOTTOM_SHEET_PEEK_HEIGHT_PERCENTAGE = 0.60f;
    private static final float HIDE_PROFILE_BUTTON_THRESHOLD = -0.5f;
    private static final String LOGGER_INSTANCE_ID_ARG = "loggerInstanceIdArg";
    private static final String EXTRA_PRELOAD_SELECTED =
            "com.android.providers.media.photopicker.extra.PRELOAD_SELECTED";

    private ViewModelProvider mViewModelProvider;
    private PickerViewModel mPickerViewModel;
    private PreloaderInstanceHolder mPreloaderInstanceHolder;

    private Selection mSelection;
    private BottomSheetBehavior mBottomSheetBehavior;
    private View mBottomBar;
    private View mBottomSheetView;
    private View mFragmentContainerView;
    private View mDragBar;
    private View mProfileButton;
    private TextView mPrivacyText;
    private TabLayout mTabLayout;
    private Toolbar mToolbar;
    private CrossProfileListeners mCrossProfileListeners;

    @NonNull
    private final MutableLiveData<Boolean> mIsItemPhotoGridViewChanged =
            new MutableLiveData<>(false);

    @ColorInt
    private int mDefaultBackgroundColor;

    @ColorInt
    private int mToolBarIconColor;

    private int mToolbarHeight = 0;
    private boolean mShouldLogCancelledResult = true;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // This is required as GET_CONTENT with type "*/*" is also received by PhotoPicker due
        // to higher priority than DocumentsUi. "*/*" mime type filter is caught as it is a superset
        // of "image/*" and "video/*".
        if (rerouteGetContentRequestIfRequired()) {
            // This activity is finishing now: we should not run the setup below,
            // BUT before we return we have to call super.onCreate() (otherwise we are we will get
            // SuperNotCalledException: Activity did not call through to super.onCreate())
            super.onCreate(savedInstanceState);
            return;
        }

        // We use the device default theme as the base theme. Apply the material them for the
        // material components. We use force "false" here, only values that are not already defined
        // in the base theme will be copied.
        getTheme().applyStyle(R.style.PickerMaterialTheme, /* force */ false);

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_photo_picker);
        mToolbar = findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        final int[] attrs = new int[]{R.attr.actionBarSize, R.attr.pickerTextColor};
        final TypedArray ta = obtainStyledAttributes(attrs);
        // Save toolbar height so that we can use it as padding for FragmentContainerView
        mToolbarHeight = ta.getDimensionPixelSize(/* index */ 0, /* defValue */ -1);
        mToolBarIconColor = ta.getColor(/* index */ 1,/* defValue */ -1);
        ta.recycle();

        mDefaultBackgroundColor = getColor(R.color.picker_background_color);

        mViewModelProvider = new ViewModelProvider(this);
        mPickerViewModel = getOrCreateViewModel();

        final Intent intent = getIntent();
        try {
            mPickerViewModel.parseValuesFromIntent(intent);
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Finish activity due to an exception while parsing extras", e);
            finishWithoutLoggingCancelledResult();
            return;
        }
        mSelection = mPickerViewModel.getSelection();
        mDragBar = findViewById(R.id.drag_bar);
        mPrivacyText = findViewById(R.id.privacy_text);
        mBottomBar = findViewById(R.id.picker_bottom_bar);
        mProfileButton = findViewById(R.id.profile_button);

        mTabLayout = findViewById(R.id.tab_layout);

        initBottomSheetBehavior();

        // Save the fragment container layout so that we can adjust the padding based on preview or
        // non-preview mode.
        mFragmentContainerView = findViewById(R.id.fragment_container);

        mCrossProfileListeners = new CrossProfileListeners();

        mPreloaderInstanceHolder = mViewModelProvider.get(PreloaderInstanceHolder.class);
        if (mPreloaderInstanceHolder.preloader != null) {
            subscribeToSelectedMediaPreloader(mPreloaderInstanceHolder.preloader);
        }

        observeRefreshUiNotificationLiveData();
        // Restore state operation should always be kept at the end of this method.
        restoreState(savedInstanceState);
        // Call this after state is restored, to use the correct LOGGER_INSTANCE_ID_ARG
        if (savedInstanceState == null) {
            final String intentAction = intent != null ? intent.getAction() : null;
            mPickerViewModel.logPickerOpened(Binder.getCallingUid(), getCallingPackage(),
                    intentAction);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mCrossProfileListeners != null) {
            // This is required to unregister any broadcast receivers.
            mCrossProfileListeners.onDestroy();
        }
    }

    /**
     * Warning: This method is needed for tests, we are not customizing anything here.
     * Allowing ourselves to control ViewModel creation helps us mock the ViewModel for test.
     */
    @VisibleForTesting
    @NonNull
    protected PickerViewModel getOrCreateViewModel() {
        return mViewModelProvider.get(PickerViewModel.class);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event){
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {

                Rect outRect = new Rect();
                mBottomSheetView.getGlobalVisibleRect(outRect);

                if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
                    mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
                }
            }
        }
        return super.dispatchTouchEvent(event);
    }

    /**
     * This method is called on action bar home button clicks if
     * {@link androidx.appcompat.app.ActionBar#setDisplayHomeAsUpEnabled(boolean)} is set
     * {@code true}.
     */
    @Override
    public boolean onSupportNavigateUp() {
        int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
        mPickerViewModel.logActionBarHomeButtonClick(backStackEntryCount);
        super.onBackPressed();
        return true;
    }

    @Override
    public void onBackPressed() {
        int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
        mPickerViewModel.logBackGestureWithStackCount(backStackEntryCount);
        super.onBackPressed();
    }

    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        mPickerViewModel.logMenuOpened();
        return super.onMenuOpened(featureId, menu);
    }

    @Override
    public void setTitle(CharSequence title) {
        super.setTitle(title);
        getSupportActionBar().setTitle(title);
    }

    /**
     * Called when owning activity is saving state to be used to restore state during creation.
     *
     * @param state Bundle to save state
     */
    @Override
    public void onSaveInstanceState(Bundle state) {
        super.onSaveInstanceState(state);
        saveBottomSheetState();
        state.putParcelable(LOGGER_INSTANCE_ID_ARG, mPickerViewModel.getInstanceId());
    }

    @Override
    public boolean onCreateOptionsMenu(@NonNull Menu menu) {
        getMenuInflater().inflate(R.menu.picker_overflow_menu, menu);
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(@NonNull Menu menu) {
        super.onPrepareOptionsMenu(menu);
        // All logic to hide/show an item in the menu must be in this method
        final MenuItem settingsMenuItem = menu.findItem(R.id.settings);

        // TODO(b/195009187): Settings menu item is hidden by default till Settings page is
        // completely developed.
        settingsMenuItem.setVisible(shouldShowSettingsScreen());

        // Browse menu item allows users to launch DocumentsUI. This item should only be shown if
        // PhotoPicker was opened via {@link #ACTION_GET_CONTENT}.
        menu.findItem(R.id.browse).setVisible(isGetContentAction());

        return menu.hasVisibleItems();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.browse:
                mPickerViewModel.logBrowseToDocumentsUi(Binder.getCallingUid(),
                        getCallingPackage());
                launchDocumentsUiAndFinishPicker();
                return true;
            case R.id.settings:
                startSettingsActivity();
                return true;
            default:
                // Continue to return the result of base class' onOptionsItemSelected(item)
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Launch the Photo Picker settings page where user can view/edit current cloud media provider.
     */
    public void startSettingsActivity() {
        final Intent intent = new Intent(this, PhotoPickerSettingsActivity.class);
        intent.putExtra(EXTRA_CURRENT_USER_ID, getCurrentUserId());
        startActivity(intent);
    }

    /**
     * @return {@code true} if the intent was re-routed to the DocumentsUI (and this
     *  {@code PhotoPickerActivity} is {@link #isFinishing()} now). {@code false} - otherwise.
     */
    private boolean rerouteGetContentRequestIfRequired() {
        final Intent intent = getIntent();
        if (!ACTION_GET_CONTENT.equals(intent.getAction())) {
            return false;
        }

        // TODO(b/232775643): Workaround to support PhotoPicker invoked from DocumentsUi.
        // GET_CONTENT for all (media and non-media) files opens DocumentsUi, but it still shows
        // "Photo Picker app option. When the user clicks on "Photo Picker", the same intent which
        // includes filters to show non-media files as well is forwarded to PhotoPicker.
        // Make sure Photo Picker is opened when the intent is explicitly forwarded by documentsUi
        if (isIntentReferredByDocumentsUi(getReferrer())) {
            Log.i(TAG, "Open PhotoPicker when a forwarded ACTION_GET_CONTENT intent is received");
            return false;
        }

        // Check if we can handle the specified MIME types.
        // If we can - do not reroute and thus return false.
        if (!MimeFilterUtils.requiresUnsupportedFilters(intent)) return false;

        launchDocumentsUiAndFinishPicker();
        return true;
    }

    private boolean isIntentReferredByDocumentsUi(Uri referrerAppUri) {
        ComponentName documentsUiComponentName = getDocumentsUiComponentName(this);
        String documentsUiPackageName = documentsUiComponentName != null
                ? documentsUiComponentName.getPackageName() : null;
        return referrerAppUri != null && referrerAppUri.getHost().equals(documentsUiPackageName);
    }

    private void launchDocumentsUiAndFinishPicker() {
        Log.i(TAG, "Launch DocumentsUI and finish picker");

        startActivityAsUser(getDocumentsUiForwardingIntent(this, getIntent()),
                UserId.CURRENT_USER.getUserHandle());
        // RESULT_CANCELLED is not returned to the calling app as the DocumentsUi result will be
        // returned. We don't have to log as this flow can be called in 2 cases:
        // 1. GET_CONTENT had non-media filters, so the user or the app should be unaffected as they
        // see that DocumentsUi was opened directly.
        // 2. User clicked on "Browse.." button, in that case we already log that event separately.
        finishWithoutLoggingCancelledResult();
    }

    @VisibleForTesting
    static Intent getDocumentsUiForwardingIntent(Context context, Intent intent) {
        intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
        intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
        intent.setComponent(getDocumentsUiComponentName(context));
        return intent;
    }

    private static ComponentName getDocumentsUiComponentName(Context context) {
        final PackageManager pm = context.getPackageManager();
        // DocumentsUI is the default handler for ACTION_OPEN_DOCUMENT
        final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        return intent.resolveActivity(pm);
    }

    private void restoreState(Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            restoreBottomSheetState();
            mPickerViewModel.setInstanceId(
                    savedInstanceState.getParcelable(LOGGER_INSTANCE_ID_ARG));
        } else {
            setupInitialLaunchState();
        }
    }

    /**
     * Sets up states for the initial launch. This includes updating common layouts, selecting
     * Photos tab item and saving the current bottom sheet state for later.
     */
    private void setupInitialLaunchState() {
        updateCommonLayouts(MODE_PHOTOS_TAB, /* title */ "");
        TabContainerFragment.show(getSupportFragmentManager());
        saveBottomSheetState();
    }

    private void initBottomSheetBehavior() {
        mBottomSheetView = findViewById(R.id.bottom_sheet);
        mBottomSheetBehavior = BottomSheetBehavior.from(mBottomSheetView);
        initStateForBottomSheet();

        mBottomSheetBehavior.addBottomSheetCallback(createBottomSheetCallBack());
        setRoundedCornersForBottomSheet();
    }

    private BottomSheetCallback createBottomSheetCallBack() {
        return new BottomSheetCallback() {
            private boolean mIsHiddenDueToBottomSheetClosing = false;
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                    mPickerViewModel.logSwipeDownExit();
                    finish();
                } else if (newState == BottomSheetBehavior.STATE_EXPANDED) {
                    mPickerViewModel.logExpandToFullScreen();
                }
                saveBottomSheetState();
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
                // slideOffset = -1 is when bottomsheet is completely hidden
                // slideOffset = 0 is when bottomsheet is in collapsed mode
                // slideOffset = 1 is when bottomsheet is in expanded mode
                // We hide the Profile button if the bottomsheet is 50% in between collapsed state
                // and hidden state.
                if (slideOffset < HIDE_PROFILE_BUTTON_THRESHOLD &&
                        mProfileButton.getVisibility() == View.VISIBLE) {
                    mProfileButton.setVisibility(View.GONE);
                    mIsHiddenDueToBottomSheetClosing = true;
                    return;
                }

                // We need to handle this state if the user is swiping till the bottom of the
                // screen but then swipes up bottom sheet suddenly
                if (slideOffset > HIDE_PROFILE_BUTTON_THRESHOLD &&
                        mIsHiddenDueToBottomSheetClosing) {
                    mProfileButton.setVisibility(View.VISIBLE);
                    mIsHiddenDueToBottomSheetClosing = false;
                }
            }
        };
    }

    private void setRoundedCornersForBottomSheet() {
        final float cornerRadius =
                getResources().getDimensionPixelSize(R.dimen.picker_top_corner_radius);
        final ViewOutlineProvider viewOutlineProvider = new ViewOutlineProvider() {
            @Override
            public void getOutline(final View view, final Outline outline) {
                outline.setRoundRect(0, 0, view.getWidth(),
                        (int)(view.getHeight() + cornerRadius), cornerRadius);
            }
        };
        mBottomSheetView.setOutlineProvider(viewOutlineProvider);
    }

    private void initStateForBottomSheet() {
        if (!isAccessibilityEnabled() && !mSelection.canSelectMultiple()
                && !isOrientationLandscape()) {
            final int peekHeight = getBottomSheetPeekHeight(this);
            mBottomSheetBehavior.setPeekHeight(peekHeight);
            mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
        } else {
            mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            mBottomSheetBehavior.setSkipCollapsed(true);
        }
    }

    /**
     * Warning: This method is visible for espresso tests, we are not customizing anything here.
     * Allowing ourselves to control the accessibility state helps us mock it for these tests.
     */
    @VisibleForTesting
    protected boolean isAccessibilityEnabled() {
        return getSystemService(AccessibilityManager.class).isEnabled();
    }

    private static int getBottomSheetPeekHeight(Context context) {
        final WindowManager windowManager = context.getSystemService(WindowManager.class);
        final Rect displayBounds = windowManager.getCurrentWindowMetrics().getBounds();
        return (int) (displayBounds.height() * BOTTOM_SHEET_PEEK_HEIGHT_PERCENTAGE);
    }

    private void restoreBottomSheetState() {
        // BottomSheet is always EXPANDED for landscape
        if (isOrientationLandscape()) {
            return;
        }
        final int savedState = mPickerViewModel.getBottomSheetState();
        if (isValidBottomSheetState(savedState)) {
            mBottomSheetBehavior.setState(savedState);
        }
    }

    private void saveBottomSheetState() {
        // Do not save state for landscape or preview mode. This is because they are always in
        // STATE_EXPANDED state.
        if (isOrientationLandscape() || !mBottomSheetView.getClipToOutline()) {
            return;
        }
        mPickerViewModel.setBottomSheetState(mBottomSheetBehavior.getState());
    }

    private boolean isValidBottomSheetState(int state) {
        return state == BottomSheetBehavior.STATE_COLLAPSED ||
                state == BottomSheetBehavior.STATE_EXPANDED;
    }

    private boolean isOrientationLandscape() {
        return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
    }

    public LiveData<Boolean> isItemPhotoGridViewChanged() {
        return mIsItemPhotoGridViewChanged;
    }

    public void setResultAndFinishSelf() {
        logPickerSelectionConfirmed(mSelection.getSelectedItems().size());
        if (shouldPreloadSelectedItems()) {
            final var uris = PickerResult.getPickerUrisForItems(
                    mSelection.getSelectedItems());
            mPickerViewModel.logPreloadingStarted(uris.size());
            mPreloaderInstanceHolder.preloader =
                    SelectedMediaPreloader.preload(/* activity */ this, uris);
            deSelectUnavailableMedia(mPreloaderInstanceHolder.preloader);
            subscribeToSelectedMediaPreloader(mPreloaderInstanceHolder.preloader);
        } else {
            setResultAndFinishSelfInternal();
        }
    }

    private void setResultAndFinishSelfInternal() {
        // In addition to the activity result, add the selected files to the MediaProvider
        // media_grants database.
        if (isUserSelectImagesForAppAction()) {
            setResultForUserSelectImagesForAppAction();
        } else {
            setResultForPickImagesOrGetContentAction();
        }

        finishWithoutLoggingCancelledResult();
    }

    private void setResultForUserSelectImagesForAppAction() {
        // Since Photopicker is in permission mode, don't send back URI grants.
        setResult(RESULT_OK);
        // The permission controller will pass the requesting package's UID here
        final Bundle extras = getIntent().getExtras();
        final int uid = extras.getInt(Intent.EXTRA_UID);
        final List<Uri> uris = getPickerUrisForItems(mSelection.getSelectedItemsWithoutGrants());
        if (!uris.isEmpty()) {
            ForegroundThread.getExecutor().execute(() -> {
                // Handle grants in another thread to not block the UI.
                grantMediaReadForPackage(getApplicationContext(), uid, uris);
                mPickerViewModel.logPickerChoiceAddedGrantsCount(uris.size(), extras);
            });
        }

        // Revoke READ_GRANT for items that were pre-granted but now in the current session user has
        // deselected them.
        if (mPickerViewModel.isManagedSelectionEnabled()) {
            final List<Uri> urisForItemsWhoseGrantsNeedsToBeRevoked = getPickerUrisForItems(
                    mSelection.getPreGrantedItemsToBeRevoked());
            if (!urisForItemsWhoseGrantsNeedsToBeRevoked.isEmpty()) {
                ForegroundThread.getExecutor().execute(() -> {
                    // Handle grants in another thread to not block the UI.
                    MediaStore.revokeMediaReadForPackages(getApplicationContext(), uid,
                            urisForItemsWhoseGrantsNeedsToBeRevoked);
                    mPickerViewModel.logPickerChoiceRevokedGrantsCount(
                            urisForItemsWhoseGrantsNeedsToBeRevoked.size(), extras);
                });
            }
        }
    }

    private void setResultForPickImagesOrGetContentAction() {
        final Intent resultData = getPickerResponseIntent(
                mSelection.canSelectMultiple(),
                mSelection.getSelectedItems());
        setResult(RESULT_OK, resultData);
    }

    private boolean shouldPreloadSelectedItems() {
        // Only preload if the cloud media may be shown in the PhotoPicker.
        if (!isCloudMediaAvailable()) {
            return false;
        }

        final boolean isGetContent = isGetContentAction();
        final boolean isPickImages = isPickImagesAction();
        final ConfigStore cs = mPickerViewModel.getConfigStore();

        if (getIntent().hasExtra(EXTRA_PRELOAD_SELECTED)) {
            if (Build.isDebuggable()
                    || (isPickImages && cs.shouldPickerRespectPreloadArgumentForPickImages())) {
                return getIntent().getBooleanExtra(EXTRA_PRELOAD_SELECTED,
                        /* default, not used */ false);
            }
        }

        if (isGetContent) {
            return cs.shouldPickerPreloadForGetContent();
        } else if (isPickImages) {
            return cs.shouldPickerPreloadForPickImages();
        } else {
            Log.w(TAG, "Not preloading selection for \"" + getIntent().getAction() + "\" action");
            return false;
        }
    }

    private void subscribeToSelectedMediaPreloader(@NonNull SelectedMediaPreloader preloader) {
        preloader.getIsFinishedLiveData().observe(
                /* lifecycleOwner */ PhotoPickerActivity.this,
                isFinished -> {
                    if (isFinished) {
                        mPickerViewModel.logPreloadingFinished();
                        setResultAndFinishSelfInternal();
                    }
                });
    }

    // This method is responsible for deselecting all  unavailable items from selection list
    // when user tries selecting unavailable could only media (not cached) while offline
    private void deSelectUnavailableMedia(@NonNull SelectedMediaPreloader preloader) {
        preloader.getUnavailableMediaIndexes().observe(
                /* lifecycleOwner */ PhotoPickerActivity.this,
                unavailableMediaIndexes -> {
                    if (unavailableMediaIndexes.size() > 0) {
                        // To notify the fragment to uncheck the unavailable items at UI those are
                        // no longer available in the selection list.
                        mIsItemPhotoGridViewChanged.postValue(true);

                        // Checking if preloading was intentionally be cancelled by the user
                        if (unavailableMediaIndexes.get(unavailableMediaIndexes.size() - 1) != -1) {
                            // Displaying  error dialog with an error message when the user tries
                            // to add unavailable cloud only media (not cached) while offline.
                            DialogUtils.showDialog(this,
                                    getResources().getString(R.string.dialog_error_title),
                                    getResources().getString(R.string.dialog_error_message));
                            mPickerViewModel.logPreloadingFailed(unavailableMediaIndexes.size());
                        } else {
                            unavailableMediaIndexes.remove(
                                    unavailableMediaIndexes.size() - 1);
                            mPickerViewModel.logPreloadingCancelled(unavailableMediaIndexes.size());
                        }
                        List<Item> selectedItems = mSelection.getSelectedItems();
                        for (var mediaIndex : unavailableMediaIndexes) {
                            mSelection.removeSelectedItem(selectedItems.get(mediaIndex));
                        }
                    }
                });
    }

    /**
     * NOTE: this may wrongly return {@code false} if called before {@link PickerViewModel} had a
     * chance to fetch the authority and the account of the current
     * {@link android.provider.CloudMediaProvider}.
     * However, this may only happen very early on in the lifecycle.
     */
    private boolean isCloudMediaAvailable() {
        return mPickerViewModel.getCloudMediaProviderAuthorityLiveData().getValue() != null
                && mPickerViewModel.getCloudMediaAccountNameLiveData().getValue() != null;
    }

    /**
     * This should be called if:
     * * We are finishing Picker explicitly before the user has seen PhotoPicker UI due to known
     *   checks/workflow.
     * * We are not returning {@link Activity#RESULT_CANCELED}
     */
    private void finishWithoutLoggingCancelledResult() {
        mShouldLogCancelledResult = false;
        finish();
    }

    @Override
    public void finish() {
        if (mShouldLogCancelledResult) {
            logPickerCancelled();
        }
        super.finish();
    }

    private void logPickerSelectionConfirmed(int countOfItemsConfirmed) {
        mPickerViewModel.logPickerConfirm(Binder.getCallingUid(), getCallingPackage(),
                countOfItemsConfirmed);
    }

    private void logPickerCancelled() {
        mPickerViewModel.logPickerCancel(Binder.getCallingUid(), getCallingPackage());
    }

    @UserIdInt
    private int getCurrentUserId() {
        final UserIdManager userIdManager = mPickerViewModel.getUserIdManager();
        return userIdManager.getCurrentUserProfileId().getIdentifier();
    }

    /**
     * Updates the common views such as Title, Toolbar, Navigation bar, status bar and bottom sheet
     * behavior
     *
     * @param mode {@link LayoutModeUtils.Mode} which describes the layout mode to update.
     * @param title the title to set for the Activity
     */
    public void updateCommonLayouts(LayoutModeUtils.Mode mode, String title) {
        updateTitle(title);
        updateToolbar(mode);
        updateStatusBarAndNavigationBar(mode);
        updateBottomSheetBehavior(mode);
        updateFragmentContainerViewPadding(mode);
        updateDragBarVisibility(mode);
        updateHeaderTextVisibility(mode);
        // The bottom bar and profile button are not shown on preview, hide them in preview. We
        // handle the visibility of them in TabFragment. We don't need to make them shown in
        // non-preview page here.
        if (mode.isPreview) {
            mBottomBar.setVisibility(View.GONE);
            mProfileButton.setVisibility(View.GONE);
        }
    }

    private void updateTitle(String title) {
        setTitle(title);
    }

    /**
     * Updates the icons and show/hide the tab layout with {@code mode}.
     *
     * @param mode {@link LayoutModeUtils.Mode} which describes the layout mode to update.
     */
    private void updateToolbar(@NonNull LayoutModeUtils.Mode mode) {
        final boolean isPreview = mode.isPreview;
        final boolean shouldShowTabLayout = mode.isPhotosTabOrAlbumsTab;
        // 1. Set the tabLayout visibility
        mTabLayout.setVisibility(shouldShowTabLayout ? View.VISIBLE : View.GONE);

        // 2. Set the toolbar color
        final ColorDrawable toolbarColor;
        if (isPreview && !shouldShowTabLayout) {
            if (isOrientationLandscape()) {
                // Toolbar in Preview will have transparent color in Landscape mode.
                toolbarColor = new ColorDrawable(getColor(android.R.color.transparent));
            } else {
                // Toolbar in Preview will have a solid color with 90% opacity in Portrait mode.
                toolbarColor = new ColorDrawable(getColor(R.color.preview_scrim_solid_color));
            }
        } else {
            toolbarColor = new ColorDrawable(mDefaultBackgroundColor);
        }
        getSupportActionBar().setBackgroundDrawable(toolbarColor);

        // 3. Set the toolbar icon.
        final Drawable icon;
        if (shouldShowTabLayout) {
            icon = getDrawable(R.drawable.ic_close);
        } else {
            icon = getDrawable(R.drawable.ic_arrow_back);
            // Preview mode has dark background, hence icons will be WHITE in color
            icon.setTint(isPreview ? Color.WHITE : mToolBarIconColor);
        }
        getSupportActionBar().setHomeAsUpIndicator(icon);
        getSupportActionBar().setHomeActionContentDescription(
                shouldShowTabLayout ? android.R.string.cancel
                        : R.string.abc_action_bar_up_description);
        if (mToolbar.getOverflowIcon() != null) {
            mToolbar.getOverflowIcon().setTint(isPreview ? Color.WHITE : mToolBarIconColor);
        }
    }

    /**
     * Updates status bar and navigation bar
     *
     * @param mode {@link LayoutModeUtils.Mode} which describes the layout mode to update.
     */
    private void updateStatusBarAndNavigationBar(@NonNull LayoutModeUtils.Mode mode) {
        final boolean isPreview = mode.isPreview;
        final int navigationBarColor = isPreview ? getColor(R.color.preview_background_color) :
                mDefaultBackgroundColor;
        getWindow().setNavigationBarColor(navigationBarColor);

        final int statusBarColor = isPreview ? getColor(R.color.preview_background_color) :
                getColor(android.R.color.transparent);
        getWindow().setStatusBarColor(statusBarColor);

        // Update the system bar appearance
        final int mask = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
        int appearance = 0;
        if (!isPreview) {
            final int uiModeNight =
                    getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;

            if (uiModeNight == Configuration.UI_MODE_NIGHT_NO) {
                // If the system is not in Dark theme, set the system bars to light mode.
                appearance = mask;
            }
        }
        getWindow().getInsetsController().setSystemBarsAppearance(appearance, mask);
    }

    /**
     * Updates the bottom sheet behavior
     *
     * @param mode {@link LayoutModeUtils.Mode} which describes the layout mode to update.
     */
    private void updateBottomSheetBehavior(@NonNull LayoutModeUtils.Mode mode) {
        final boolean isPreview = mode.isPreview;
        if (mBottomSheetView != null) {
            mBottomSheetView.setClipToOutline(!isPreview);
            // TODO(b/197241815): Add animation downward swipe for preview should go back to
            // the photo in photos grid
            mBottomSheetBehavior.setDraggable(!isPreview);
        }
        if (isPreview) {
            if (mBottomSheetBehavior.getState() != BottomSheetBehavior.STATE_EXPANDED) {
                // Sets bottom sheet behavior state to STATE_EXPANDED if it's not already expanded.
                // This is useful when user goes to Preview mode which is always Full screen.
                // TODO(b/197241815): Add animation preview to full screen and back transition to
                // partial screen. This is similar to long press animation.
                mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        } else {
            restoreBottomSheetState();
        }
    }

    /**
     * Updates the FragmentContainerView padding.
     * <p>
     * For Preview mode, toolbar overlaps the Fragment content, hence the padding will be set to 0.
     * For Non-Preview mode, toolbar doesn't overlap the contents of the fragment, hence we set the
     * padding as the height of the toolbar.
     */
    private void updateFragmentContainerViewPadding(@NonNull LayoutModeUtils.Mode mode) {
        if (mFragmentContainerView == null) return;

        final int topPadding;
        if (mode.isPreview) {
            topPadding = 0;
        } else {
            topPadding = mToolbarHeight;
        }

        mFragmentContainerView.setPadding(mFragmentContainerView.getPaddingLeft(),
                topPadding, mFragmentContainerView.getPaddingRight(),
                mFragmentContainerView.getPaddingBottom());
    }

    private void updateDragBarVisibility(@NonNull LayoutModeUtils.Mode mode) {
        final boolean shouldShowDragBar = !mode.isPreview;
        mDragBar.setVisibility(shouldShowDragBar ? View.VISIBLE : View.GONE);
    }

    private void updateHeaderTextVisibility(@NonNull LayoutModeUtils.Mode mode) {
        // The privacy text is only shown on the Photos tab and Albums tab when not in
        // permission select mode.
        final boolean shouldShowPrivacyMessage = mode.isPhotosTabOrAlbumsTab;

        if (!shouldShowPrivacyMessage) {
            mPrivacyText.setVisibility(View.GONE);
            return;
        }

        if (mPickerViewModel.isUserSelectForApp()) {
            mPrivacyText.setText(R.string.picker_header_permissions);
            mPrivacyText.setTextSize(
                    TypedValue.COMPLEX_UNIT_PX,
                    getResources().getDimension(R.dimen.picker_user_select_header_text_size));
        } else {
            mPrivacyText.setText(R.string.picker_privacy_message);
            mPrivacyText.setTextSize(
                    TypedValue.COMPLEX_UNIT_PX,
                    getResources().getDimension(R.dimen.picker_privacy_text_size));
        }

        mPrivacyText.setVisibility(View.VISIBLE);
    }

    /**
     * Reset to Photo Picker initial launch state (Photos grid tab) in personal profile mode.
     */
    private void resetToPersonalProfile() {
        // Clear all the fragments in the FragmentManager
        final FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.popBackStackImmediate(/* name */ null,
                FragmentManager.POP_BACK_STACK_INCLUSIVE);

        // Reset all content to the personal profile
        mPickerViewModel.resetToPersonalProfile();

        // Set up the fragments same as the initial launch state
        setupInitialLaunchState();
    }

    /**
     * Reset to Photo Picker initial launch state (Photos grid tab) in the current profile mode.
     */
    private void resetInCurrentProfile() {
        // Clear all the fragments in the FragmentManager
        final FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.popBackStackImmediate(/* name */ null,
                FragmentManager.POP_BACK_STACK_INCLUSIVE);

        // Reset all content in the current profile
        mPickerViewModel.resetAllContentInCurrentProfile();

        // Set up the fragments same as the initial launch state
        setupInitialLaunchState();
    }

    /**
     * Returns {@code true} if settings page is enabled.
     */
    private boolean shouldShowSettingsScreen() {
        if (mPickerViewModel.shouldShowOnlyLocalFeatures()) {
            return false;
        }

        final ComponentName componentName = new ComponentName(this,
                PhotoPickerSettingsActivity.class);
        return getPackageManager().getComponentEnabledSetting(componentName)
                == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
    }

    /**
     * Returns {@code true} if intent action is {@link ACTION_GET_CONTENT}.
     */
    private boolean isGetContentAction() {
        return ACTION_GET_CONTENT.equals(getIntent().getAction());
    }

    /**
     * Returns {@code true} if intent action is {@link ACTION_PICK_IMAGES}.
     */
    private boolean isPickImagesAction() {
        return ACTION_PICK_IMAGES.equals(getIntent().getAction());
    }

    /**
     * Returns {@code true} if intent action is {@link ACTION_USER_SELECT_IMAGES_FOR_APP}
     * (the 3-way storage permission grant flow)
     */
    private boolean isUserSelectImagesForAppAction() {
        return ACTION_USER_SELECT_IMAGES_FOR_APP.equals(getIntent().getAction());
    }

    private class CrossProfileListeners {

        private final List<String> MANAGED_PROFILE_FILTER_ACTIONS = Lists.newArrayList(
                Intent.ACTION_MANAGED_PROFILE_ADDED, // add profile button switch
                Intent.ACTION_MANAGED_PROFILE_REMOVED, // remove profile button switch
                Intent.ACTION_MANAGED_PROFILE_UNLOCKED, // activate profile button switch
                Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE // disable profile button switch
        );

        private final UserIdManager mUserIdManager;

        public CrossProfileListeners() {
            mUserIdManager = mPickerViewModel.getUserIdManager();

            registerBroadcastReceivers();
        }

        public void onDestroy() {
            unregisterReceiver(mReceiver);
        }

        private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();

                final UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
                final UserId userId = UserId.of(userHandle);

                // We only need to refresh the layout when the received profile user is the
                // managed user corresponding to the current profile or a new work profile is added
                // for the current user.
                if (!userId.equals(mUserIdManager.getManagedUserId()) &&
                        !action.equals(Intent.ACTION_MANAGED_PROFILE_ADDED)) {
                    return;
                }

                switch (action) {
                    case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
                        handleWorkProfileOff();
                        break;
                    case Intent.ACTION_MANAGED_PROFILE_REMOVED:
                        handleWorkProfileRemoved();
                        break;
                    case Intent.ACTION_MANAGED_PROFILE_UNLOCKED:
                        handleWorkProfileOn();
                        break;
                    case Intent.ACTION_MANAGED_PROFILE_ADDED:
                        handleWorkProfileAdded();
                        break;
                    default:
                        // do nothing
                }
            }
        };

        private void registerBroadcastReceivers() {
            final IntentFilter managedProfileFilter = new IntentFilter();
            for (String managedProfileAction : MANAGED_PROFILE_FILTER_ACTIONS) {
                managedProfileFilter.addAction(managedProfileAction);
            }
            registerReceiver(mReceiver, managedProfileFilter);
        }

        private void handleWorkProfileOff() {
            if (mUserIdManager.isManagedUserSelected()) {
                switchToPersonalProfileInitialLaunchState();
            }
            mUserIdManager.updateWorkProfileOffValue();
        }

        private void handleWorkProfileRemoved() {
            if (mUserIdManager.isManagedUserSelected()) {
                switchToPersonalProfileInitialLaunchState();
            }
            mUserIdManager.resetUserIds();
        }

        private void handleWorkProfileAdded() {
            mUserIdManager.resetUserIds();
        }

        private void handleWorkProfileOn() {
            // Update UI for switch to profile button
            // When the managed profile becomes available, the provider may not be available
            // immediately, we need to check if it is ready before we reload the content.
            mUserIdManager.waitForMediaProviderToBeAvailable();
        }

        private void switchToPersonalProfileInitialLaunchState() {
            // We reset the state of the PhotoPicker as we do not want to make any
            // assumptions on the state of the PhotoPicker when it was in Work Profile mode.
            resetToPersonalProfile();
        }
    }

    /**
     * A {@link ViewModel} class only responsible for keeping track of "active"
     * {@link SelectedMediaPreloader} instance (if any).
     * This class has to be public, since somewhere in {@link ViewModelProvider} it will try to use
     * reflection to create an instance of this class.
     */
    public static class PreloaderInstanceHolder extends ViewModel {
        @Nullable
        SelectedMediaPreloader preloader;
    }

    /**
     * Reset the Picker view model content when launched with cloud features and notified to
     * refresh the UI.
     */
    private void observeRefreshUiNotificationLiveData() {
        mPickerViewModel.shouldRefreshUiLiveData()
                .observe(this, shouldRefresh -> {
                    if (shouldRefresh && !mPickerViewModel.shouldShowOnlyLocalFeatures()) {
                        resetInCurrentProfile();
                    }
                });
    }
}
