/*
 * Copyright (C) 2017 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.wallpaper.picker;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowInsets;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

import com.android.wallpaper.R;
import com.android.wallpaper.asset.Asset;
import com.android.wallpaper.compat.ButtonDrawableSetterCompat;
import com.android.wallpaper.config.Flags;
import com.android.wallpaper.model.Category;
import com.android.wallpaper.model.ImageWallpaperInfo;
import com.android.wallpaper.model.WallpaperInfo;
import com.android.wallpaper.module.CurrentWallpaperInfoFactory;
import com.android.wallpaper.module.CurrentWallpaperInfoFactory.WallpaperInfoCallback;
import com.android.wallpaper.module.DailyLoggingAlarmScheduler;
import com.android.wallpaper.module.ExploreIntentChecker;
import com.android.wallpaper.module.FormFactorChecker;
import com.android.wallpaper.module.Injector;
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.module.NetworkStatusNotifier;
import com.android.wallpaper.module.NetworkStatusNotifier.NetworkStatus;
import com.android.wallpaper.module.UserEventLogger;
import com.android.wallpaper.module.UserEventLogger.WallpaperSetFailureReason;
import com.android.wallpaper.module.WallpaperPersister;
import com.android.wallpaper.module.WallpaperPersister.Destination;
import com.android.wallpaper.module.WallpaperPersister.SetWallpaperCallback;
import com.android.wallpaper.module.WallpaperPersister.WallpaperPosition;
import com.android.wallpaper.module.WallpaperPreferences;
import com.android.wallpaper.module.WallpaperPreferences.PresentationMode;
import com.android.wallpaper.module.WallpaperRotationRefresher;
import com.android.wallpaper.module.WallpaperRotationRefresher.Listener;
import com.android.wallpaper.picker.AppbarFragment.AppbarFragmentHost;
import com.android.wallpaper.picker.CategoryFragment.CategoryFragmentHost;
import com.android.wallpaper.picker.WallpaperDisabledFragment.WallpaperSupportLevel;
import com.android.wallpaper.picker.individual.IndividualPickerFragment;
import com.android.wallpaper.util.ActivityUtils;
import com.android.wallpaper.util.ResourceUtils;
import com.android.wallpaper.util.ScreenSizeCalculator;
import com.android.wallpaper.util.ThrowableAnalyzer;

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.android.material.tabs.TabLayout.OnTabSelectedListener;
import com.google.android.material.tabs.TabLayout.Tab;

import java.util.List;

/**
 * Activity allowing users to select a category of wallpapers to choose from.
 */
public class TopLevelPickerActivity extends BaseActivity implements WallpapersUiContainer,
        CurrentWallpaperBottomSheetPresenter, SetWallpaperErrorDialogFragment.Listener,
        MyPhotosStarter, AppbarFragmentHost, CategoryFragmentHost {

    private static final String TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT =
            "toplevel_set_wallpaper_error_dialog";

    private static final String TAG = "TopLevelPicker";
    private static final String KEY_SELECTED_CATEGORY_TAB = "selected_category_tab";

    private WallpaperPickerDelegate mDelegate;
    private int mLastSelectedCategoryTabIndex;
    private UserEventLogger mUserEventLogger;
    private NetworkStatusNotifier mNetworkStatusNotifier;
    private NetworkStatusNotifier.Listener mNetworkStatusListener;
    private WallpaperPersister mWallpaperPersister;
    private WallpaperPreferences mWallpaperPreferences;
    private boolean mWasCustomPhotoWallpaperSet;
    @WallpaperPosition
    private int mCustomPhotoWallpaperPosition;

    /**
     * Progress dialogs for "refresh daily wallpaper" and "set wallpaper" operations.
     */
    private ProgressDialog mRefreshWallpaperProgressDialog;
    private ProgressDialog mSetWallpaperProgressDialog;

    /**
     * Designates a test mode of operation -- in which certain UI features are disabled to allow for
     * UI tests to run correctly.
     */
    private boolean mTestingMode;

    /**
     * UI for the "currently set wallpaper" BottomSheet.
     */
    private LinearLayout mBottomSheet;
    private ImageView mCurrentWallpaperImage;
    private TextView mCurrentWallpaperPresentationMode;
    private TextView mCurrentWallpaperTitle;
    private TextView mCurrentWallpaperSubtitle;
    private Button mCurrentWallpaperExploreButton;
    private Button mCurrentWallpaperSkipWallpaperButton;
    private FrameLayout mFragmentContainer;
    private FrameLayout mLoadingIndicatorContainer;
    private LinearLayout mWallpaperPositionOptions;

    /**
     * Staged error dialog fragments that were unable to be shown when the activity didn't allow
     * committing fragment transactions.
     */
    private SetWallpaperErrorDialogFragment mStagedSetWallpaperErrorDialogFragment;

    /**
     * A wallpaper pending set to the device--we retain a reference to this in order to facilitate
     * retry or re-crop operations.
     */
    private WallpaperInfo mPendingSetWallpaperInfo;

    private int getTextColorForWallpaperPositionButton(boolean isSelected) {
        int textColorId = isSelected
                ? android.R.attr.colorAccent
                : android.R.attr.textColorTertiary;
        return ResourceUtils.getColorAttr(this, textColorId);
    }

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

        mLastSelectedCategoryTabIndex = -1;

        Injector injector = InjectorProvider.getInjector();
        mDelegate = new WallpaperPickerDelegate(this, this, injector);
        mUserEventLogger = injector.getUserEventLogger(this);
        mNetworkStatusNotifier = injector.getNetworkStatusNotifier(this);
        mWallpaperPersister = injector.getWallpaperPersister(this);
        mWallpaperPreferences = injector.getPreferences(this);
        mWasCustomPhotoWallpaperSet = false;

        mDelegate.getCategoryProvider().resetIfNeeded();

        @WallpaperSupportLevel int wallpaperSupportLevel = mDelegate.getWallpaperSupportLevel();
        if (wallpaperSupportLevel != WallpaperDisabledFragment.SUPPORTED_CAN_SET) {
            setContentView(R.layout.activity_top_level_picker);

            FragmentManager fm = getSupportFragmentManager();
            WallpaperDisabledFragment wallpaperDisabledFragment =
                    WallpaperDisabledFragment.newInstance(wallpaperSupportLevel);
            fm.beginTransaction()
                    .add(R.id.fragment_container, wallpaperDisabledFragment)
                    .commit();
            return;
        }

        if (mDelegate.getFormFactor() == FormFactorChecker.FORM_FACTOR_MOBILE) {
            initializeMobile(true /* shouldForceRefresh */);
        } else { // DESKTOP
            initializeDesktop(savedInstanceState);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        boolean provisioned = Settings.Global.getInt(getContentResolver(),
                Settings.Global.DEVICE_PROVISIONED, 0) != 0;

        mUserEventLogger.logResumed(provisioned, true);
        // Show the staged 'load wallpaper' or 'set wallpaper' error dialog fragments if there is one
        // that was unable to be shown earlier when this fragment's hosting activity didn't allow
        // committing fragment transactions.
        if (mStagedSetWallpaperErrorDialogFragment != null) {
            mStagedSetWallpaperErrorDialogFragment.show(
                    getSupportFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
            mStagedSetWallpaperErrorDialogFragment = null;
        }
    }

    @Override
    protected void onStop() {
        mUserEventLogger.logStopped();
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mDelegate.cleanUp();
        if (mNetworkStatusListener != null) {
            mNetworkStatusNotifier.unregisterListener(mNetworkStatusListener);
        }

        if (mRefreshWallpaperProgressDialog != null) {
            mRefreshWallpaperProgressDialog.dismiss();
        }
        if (mSetWallpaperProgressDialog != null) {
            mSetWallpaperProgressDialog.dismiss();
        }
    }

    @Override
    public void onBackPressed() {
        Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
        if (fragment != null && fragment.getChildFragmentManager().popBackStackImmediate()) {
            return;
        }
        super.onBackPressed();
    }

    @Override
    public void requestCustomPhotoPicker(PermissionChangedListener listener) {
        mDelegate.requestCustomPhotoPicker(listener);
    }

    @Override
    public void requestExternalStoragePermission(PermissionChangedListener listener) {
        mDelegate.requestExternalStoragePermission(listener);
    }

    /**
     * Returns whether READ_EXTERNAL_STORAGE has been granted for the application.
     */
    public boolean isReadExternalStoragePermissionGranted() {
        return mDelegate.isReadExternalStoragePermissionGranted();
    }

    private void initializeMobile(boolean shouldForceRefresh) {
        setContentView(R.layout.activity_top_level_picker);
        if (ActivityUtils.isSUWMode(getBaseContext())) {
            findViewById(R.id.fragment_main).setFitsSystemWindows(/* fitSystemWindows= */ true);
        }
        getWindow().getDecorView().setSystemUiVisibility(
                getWindow().getDecorView().getSystemUiVisibility()
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        View fragmentContainer = findViewById(R.id.fragment_container);
        fragmentContainer.setOnApplyWindowInsetsListener((view, windowInsets) -> {
            view.setPadding(view.getPaddingLeft(), windowInsets.getSystemWindowInsetTop(),
                    view.getPaddingRight(), view.getPaddingBottom());
            // Consume only the top inset (status bar), to let other content in the Activity consume
            // the nav bar (ie, by using "fitSystemWindows")
            if (VERSION.SDK_INT >= VERSION_CODES.Q) {
                WindowInsets.Builder builder = new WindowInsets.Builder(windowInsets);
                builder.setSystemWindowInsets(Insets.of(windowInsets.getSystemWindowInsetLeft(),
                        0, windowInsets.getStableInsetRight(),
                        windowInsets.getSystemWindowInsetBottom()));
                return builder.build();
            } else {
                return windowInsets.replaceSystemWindowInsets(
                        windowInsets.getSystemWindowInsetLeft(),
                        0, windowInsets.getStableInsetRight(),
                        windowInsets.getSystemWindowInsetBottom());
            }
        });

        // Set toolbar as the action bar.
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragment_container);

        if (fragment == null) {
            // App launch specific logic: log the "app launch source" event.
            mUserEventLogger.logAppLaunched(getIntent());
            mWallpaperPreferences.incrementAppLaunched();
            DailyLoggingAlarmScheduler.setAlarm(getApplicationContext());

            CategoryFragment newFragment = CategoryFragment.newInstance(
                    getString(R.string.wallpaper_app_name));
            fm.beginTransaction()
                    .add(R.id.fragment_container, newFragment)
                    .commit();
        }
    }

    private void initializeDesktop(Bundle savedInstanceState) {
        setContentView(R.layout.activity_top_level_desktop);

        mBottomSheet = (LinearLayout) findViewById(R.id.bottom_sheet);
        mCurrentWallpaperImage = (ImageView) mBottomSheet.findViewById(R.id.current_wallpaper_image);
        mCurrentWallpaperImage.getLayoutParams().width = getSingleWallpaperImageWidthPx();

        mCurrentWallpaperPresentationMode =
                (TextView) mBottomSheet.findViewById(R.id.current_wallpaper_presentation_mode);
        mCurrentWallpaperTitle = (TextView) findViewById(R.id.current_wallpaper_title);
        mCurrentWallpaperSubtitle = (TextView) findViewById(R.id.current_wallpaper_subtitle);
        mCurrentWallpaperExploreButton = (Button) findViewById(
                R.id.current_wallpaper_explore_button);
        mCurrentWallpaperSkipWallpaperButton = (Button) findViewById(
                R.id.current_wallpaper_skip_wallpaper_button);
        mFragmentContainer = (FrameLayout) findViewById(R.id.fragment_container);
        mLoadingIndicatorContainer = (FrameLayout) findViewById(R.id.loading_indicator_container);
        mWallpaperPositionOptions = (LinearLayout) findViewById(
                R.id.desktop_wallpaper_position_options);

        final TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        tabLayout.addOnTabSelectedListener(new OnTabSelectedListener() {
            @Override
            public void onTabSelected(Tab tab) {
                Category category = (Category) tab.getTag();
                showCategoryDesktop(category.getCollectionId());
                mLastSelectedCategoryTabIndex = tabLayout.getSelectedTabPosition();
            }

            @Override
            public void onTabUnselected(Tab tab) {
            }

            @Override
            public void onTabReselected(Tab tab) {
                Category category = (Category) tab.getTag();
                // If offline, "My photos" may be the only visible category. In this case we want to allow
                // re-selection so user can still select a photo as wallpaper while offline.
                if (!category.isEnumerable()) {
                    onTabSelected(tab);
                }
            }
        });

        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragment_container);

        if (fragment == null) {
            // App launch specific logic: log the "app launch source" event.
            mUserEventLogger.logAppLaunched(getIntent());
            mWallpaperPreferences.incrementAppLaunched();
            DailyLoggingAlarmScheduler.setAlarm(getApplicationContext());
        }

        mNetworkStatusListener = new NetworkStatusNotifier.Listener() {
            @Override
            public void onNetworkChanged(@NetworkStatus int networkStatus) {
                initializeDesktopBasedOnNetwork(networkStatus, savedInstanceState);
            }
        };
        // Upon registering a listener, the onNetworkChanged method is immediately called with the
        // initial network status.
        mNetworkStatusNotifier.registerListener(mNetworkStatusListener);
    }

    private void initializeDesktopBasedOnNetwork(@NetworkStatus int networkStatus,
                                                 Bundle savedInstanceState) {
        if (networkStatus == NetworkStatusNotifier.NETWORK_CONNECTED) {
            initializeDesktopOnline(savedInstanceState);
        } else {
            initializeDesktopOffline();
        }
    }

    private void initializeDesktopOnline(Bundle savedInstanceState) {
        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragment_container);

        // Require a category refresh if this is the first load of the app or if the app is now
        // returning online after having been offline.
        boolean forceCategoryRefresh = fragment == null || fragment instanceof OfflineDesktopFragment;

        if (fragment != null) {
            fm.beginTransaction()
                    .remove(fragment)
                    .commit();
        }

        mLastSelectedCategoryTabIndex = savedInstanceState != null
                ? savedInstanceState.getInt(KEY_SELECTED_CATEGORY_TAB) : -1;
        mDelegate.populateCategories(forceCategoryRefresh);

        setDesktopLoading(true);
        setUpBottomSheet();
        refreshCurrentWallpapers(null /* refreshListener */);
    }

    private void initializeDesktopOffline() {
        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragment_container);

        if (fragment != null) {
            fm.beginTransaction()
                    .remove(fragment)
                    .commit();
        }
        OfflineDesktopFragment newFragment = new OfflineDesktopFragment();
        fm.beginTransaction()
                .add(R.id.fragment_container, newFragment)
                .commit();

        // Reset the last selected category tab index to ensure the app doesn't try to reselect a
        // tab for a category not yet repopulated.
        mLastSelectedCategoryTabIndex = -1;

        mDelegate.populateCategories(/* forceRefresh= */ true);

        setDesktopLoading(false);
        setCurrentWallpapersExpanded(false);
    }

    /**
     * Sets the status of the loading indicator overlay in desktop mode.
     *
     * @param loading Whether an indeterminate loading indicator is displayed in place of the main
     *                fragment.
     */
    private void setDesktopLoading(boolean loading) {
        if (loading) {
            mLoadingIndicatorContainer.setVisibility(View.VISIBLE);
            mFragmentContainer.setVisibility(View.GONE);
        } else {
            mLoadingIndicatorContainer.setVisibility(View.GONE);
            mFragmentContainer.setVisibility(View.VISIBLE);
        }
    }

    /**
     * Returns the width (in physical px) to use for the "currently set wallpaper" thumbnail.
     */
    private int getSingleWallpaperImageWidthPx() {
        final float screenAspectRatio =
                ScreenSizeCalculator.getInstance().getScreenAspectRatio(this);

        int height = getResources().getDimensionPixelSize(
                R.dimen.current_wallpaper_bottom_sheet_thumb_height);
        return (int) (height / screenAspectRatio);
    }

    /**
     * Enables and populates the "Currently set" wallpaper BottomSheet.
     */
    private void setUpBottomSheet() {
        mBottomSheet.setVisibility(View.VISIBLE);

        if (Flags.skipDailyWallpaperButtonEnabled) {
            // Add "next" icon to the Next Wallpaper button
            Drawable nextWallpaperButtonDrawable = getResources().getDrawable(
                    R.drawable.ic_refresh_18px);

            // This Drawable's state is shared across the app, so make a copy of it before applying a
            // color tint as not to affect other clients elsewhere in the app.
            nextWallpaperButtonDrawable =
                    nextWallpaperButtonDrawable.getConstantState().newDrawable().mutate();
            // Color the "compass" icon with the accent color.
            nextWallpaperButtonDrawable.setColorFilter(
                    ResourceUtils.getColorAttr(this,
                            android.R.attr.colorAccent), Mode.SRC_IN);
            ButtonDrawableSetterCompat.setDrawableToButtonStart(
                    mCurrentWallpaperSkipWallpaperButton, nextWallpaperButtonDrawable);
        }

        final BottomSheetBehavior<LinearLayout> bottomSheetBehavior =
                BottomSheetBehavior.from(mBottomSheet);
        bottomSheetBehavior.setBottomSheetCallback(new BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View view, int i) {
            }

            @Override
            public void onSlide(@NonNull View view, float slideOffset) {
                float alpha;
                if (slideOffset >= 0) {
                    alpha = slideOffset;
                } else {
                    alpha = 1f - slideOffset;
                }
                LinearLayout bottomSheetContents = findViewById(R.id.bottom_sheet_contents);
                bottomSheetContents.setAlpha(alpha);
            }
        });
    }

    /**
     * Enables a test mode of operation -- in which certain UI features are disabled to allow for
     * UI tests to run correctly. Works around issue in ProgressDialog currently where the dialog
     * constantly keeps the UI thread alive and blocks a test forever.
     */
    void setTestingMode(boolean testingMode) {
        mTestingMode = testingMode;
    }

    /**
     * Obtains the {@link WallpaperInfo} object(s) representing the wallpaper(s) currently set to the
     * device from the {@link CurrentWallpaperInfoFactory} and displays them in the BottomSheet.
     */
    @Override
    public void refreshCurrentWallpapers(@Nullable RefreshListener refreshListener) {
        final Injector injector = InjectorProvider.getInjector();
        final Context appContext = getApplicationContext();

        CurrentWallpaperInfoFactory factory = injector.getCurrentWallpaperFactory(this);
        factory.createCurrentWallpaperInfos(new WallpaperInfoCallback() {
            @Override
            public void onWallpaperInfoCreated(
                    final WallpaperInfo homeWallpaper,
                    @Nullable final WallpaperInfo lockWallpaper,
                    @PresentationMode final int presentationMode) {

                if (isDestroyed()) {
                    return;
                }

                // Fetch the home wallpaper's thumbnail asset asynchronously to work around expensive
                // method call to WallpaperManager#getWallpaperFile made from the CurrentWallpaperInfoVN
                // getAsset() method.
                AssetReceiver assetReceiver = (Asset thumbAsset) -> {
                    if (isDestroyed()) {
                        return;
                    }

                    homeWallpaper.getThumbAsset(appContext).loadDrawableWithTransition(
                            TopLevelPickerActivity.this,
                            mCurrentWallpaperImage,
                            200 /* transitionDurationMillis */,
                            () -> {
                                if (refreshListener != null) {
                                    refreshListener.onCurrentWallpaperRefreshed();
                                }
                            },
                            Color.TRANSPARENT);
                };
                new FetchThumbAssetTask(appContext, homeWallpaper, assetReceiver).executeOnExecutor(
                        AsyncTask.THREAD_POOL_EXECUTOR);

                mCurrentWallpaperPresentationMode.setText(
                        AttributionFormatter.getHumanReadableWallpaperPresentationMode(
                                TopLevelPickerActivity.this, presentationMode));

                List<String> attributions = homeWallpaper.getAttributions(appContext);
                if (attributions.size() > 0 && attributions.get(0) != null) {
                    mCurrentWallpaperTitle.setText(attributions.get(0));
                }

                mCurrentWallpaperSubtitle.setText(
                        AttributionFormatter.formatWallpaperSubtitle(appContext, homeWallpaper));

                final String actionUrl = homeWallpaper.getActionUrl(appContext);
                if (actionUrl != null && !actionUrl.isEmpty()) {
                    Uri exploreUri = Uri.parse(actionUrl);

                    ExploreIntentChecker intentChecker = injector.getExploreIntentChecker(appContext);
                    intentChecker.fetchValidActionViewIntent(exploreUri, (@Nullable Intent exploreIntent) -> {
                        if (exploreIntent != null && !isDestroyed()) {
                            // Set the icon for the button
                            Drawable exploreButtonDrawable = getResources().getDrawable(
                                    homeWallpaper.getActionIconRes(appContext));

                            // This Drawable's state is shared across the app, so make a copy of it
                            // before applying a color tint as not to affect other clients elsewhere
                            // in the app.
                            exploreButtonDrawable = exploreButtonDrawable.getConstantState()
                                    .newDrawable().mutate();
                            // Color the "compass" icon with the accent color.
                            exploreButtonDrawable.setColorFilter(
                                    ResourceUtils.getColorAttr(TopLevelPickerActivity.this,
                                            android.R.attr.colorAccent), Mode.SRC_IN);

                            ButtonDrawableSetterCompat.setDrawableToButtonStart(
                                    mCurrentWallpaperExploreButton, exploreButtonDrawable);
                            mCurrentWallpaperExploreButton.setText(getString(
                                    homeWallpaper.getActionLabelRes(appContext)));
                            mCurrentWallpaperExploreButton.setVisibility(View.VISIBLE);
                            mCurrentWallpaperExploreButton.setOnClickListener(new OnClickListener() {
                                @Override
                                public void onClick(View v) {
                                    mUserEventLogger.logActionClicked(
                                            homeWallpaper.getCollectionId(appContext),
                                            homeWallpaper.getActionLabelRes(appContext));
                                    startActivity(exploreIntent);
                                }
                            });
                        }
                    });
                } else {
                    mCurrentWallpaperExploreButton.setVisibility(View.GONE);
                }

                // Hide the wallpaper position options UI if the current home wallpaper is not from
                // "my photos".
                String homeCollectionId = homeWallpaper.getCollectionId(TopLevelPickerActivity.this);
                if (mWallpaperPositionOptions != null
                        && homeCollectionId != null // May be null if app is being used for the first time.
                        && !homeCollectionId.equals(getString(R.string.image_wallpaper_collection_id))) {
                    mWallpaperPositionOptions.setVisibility(View.GONE);
                }

                boolean showSkipWallpaperButton = Flags.skipDailyWallpaperButtonEnabled
                        && presentationMode == WallpaperPreferences.PRESENTATION_MODE_ROTATING;
                if (showSkipWallpaperButton) {
                    mCurrentWallpaperSkipWallpaperButton.setVisibility(View.VISIBLE);
                    mCurrentWallpaperSkipWallpaperButton.setOnClickListener(
                            v -> refreshDailyWallpaper());
                } else {
                    mCurrentWallpaperSkipWallpaperButton.setVisibility(View.GONE);
                }

                if (refreshListener != null) {
                    refreshListener.onCurrentWallpaperRefreshed();
                }
            }
        }, true /* forceRefresh */);
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        FormFactorChecker formFactorChecker = InjectorProvider.getInjector().getFormFactorChecker(this);
        if (formFactorChecker.getFormFactor() == FormFactorChecker.FORM_FACTOR_DESKTOP) {
            TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

            // tabLayout is only present when the main IndividualPickerFragment is present (as
            // opposed to
            // the WallpaperDisabledFragment), so need this null check.
            if (tabLayout != null) {
                savedInstanceState.putInt(KEY_SELECTED_CATEGORY_TAB, tabLayout.getSelectedTabPosition());
            }
        }

        super.onSaveInstanceState(savedInstanceState);
    }

    @Override
    @Nullable
    public CategorySelectorFragment getCategorySelectorFragment() {
        if (mDelegate.getFormFactor() != FormFactorChecker.FORM_FACTOR_MOBILE) {
            return null;
        }
        FragmentManager fm = getSupportFragmentManager();
        return ((CategoryFragment) fm.findFragmentById(
                R.id.fragment_container)).getCategorySelectorFragment();
    }

    /**
     * Populates the category tabs on DESKTOP form factor.
     *
     * @param selectedTabPosition The position of the tab to show as selected, or -1 if no particular
     *                            tab should be selected (in which case: the tab of the category for the currently set
     *                            wallpaper will be selected if enumerable; if not, the first enumerable category's tab will
     *                            be selected).
     */
    private void populateCategoryTabs(int selectedTabPosition) {
        final TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        tabLayout.removeAllTabs();

        String currentlySetCollectionId = mDelegate.getPreferences().getHomeWallpaperCollectionId();

        Tab tabToSelect = null;
        Tab firstEnumerableCategoryTab = null;
        for (int i = 0; i < mDelegate.getCategoryProvider().getSize(); i++) {
            Category category = mDelegate.getCategoryProvider().getCategory(i);

            Tab tab = tabLayout.newTab();
            tab.setText(category.getTitle());
            tab.setTag(category);
            tabLayout.addTab(tab, false /* setSelected */);

            if (firstEnumerableCategoryTab == null && category.isEnumerable()) {
                firstEnumerableCategoryTab = tab;
            }

            boolean shouldSelectTab = (i == selectedTabPosition)
                    || (selectedTabPosition == -1
                    && tabToSelect == null
                    && category.isEnumerable()
                    && currentlySetCollectionId != null
                    && currentlySetCollectionId.equals(category.getCollectionId()));

            if (shouldSelectTab) {
                tabToSelect = tab;
            }
        }

        // If the above loop did not identify a specific tab to select, then just select the tab for
        // the first enumerable category.
        if (tabToSelect == null) {
            tabToSelect = firstEnumerableCategoryTab;
        }

        // There may be no enumerable tabs (e.g., offline case), so we need to null-check again.
        if (tabToSelect != null) {
            tabToSelect.select();
        }
    }

    /**
     * Refreshes the current wallpaper in a daily wallpaper rotation.
     */
    private void refreshDailyWallpaper() {
        // ProgressDialog endlessly updates the UI thread, keeping it from going idle which therefore
        // causes Espresso to hang once the dialog is shown.
        if (!mTestingMode) {
            int themeResId;
            if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
                themeResId = R.style.ProgressDialogThemePreL;
            } else {
                themeResId = R.style.LightDialogTheme;
            }
            mRefreshWallpaperProgressDialog = new ProgressDialog(this, themeResId);
            mRefreshWallpaperProgressDialog.setTitle(null);
            mRefreshWallpaperProgressDialog.setMessage(
                    getResources().getString(R.string.refreshing_daily_wallpaper_dialog_message));
            mRefreshWallpaperProgressDialog.setIndeterminate(true);
            mRefreshWallpaperProgressDialog.show();
        }

        WallpaperRotationRefresher wallpaperRotationRefresher =
                InjectorProvider.getInjector().getWallpaperRotationRefresher();
        wallpaperRotationRefresher.refreshWallpaper(this, new Listener() {
            @Override
            public void onRefreshed() {
                if (isDestroyed()) {
                    return;
                }

                if (mRefreshWallpaperProgressDialog != null) {
                    mRefreshWallpaperProgressDialog.dismiss();
                }

                refreshCurrentWallpapers(null /* refreshListener */);
            }

            @Override
            public void onError() {
                if (mRefreshWallpaperProgressDialog != null) {
                    mRefreshWallpaperProgressDialog.dismiss();
                }

                AlertDialog errorDialog = new AlertDialog.Builder(
                        TopLevelPickerActivity.this, R.style.LightDialogTheme)
                        .setMessage(R.string.refresh_daily_wallpaper_failed_message)
                        .setPositiveButton(android.R.string.ok, null /* onClickListener */)
                        .create();
                errorDialog.show();
            }
        });
    }

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

        if (requestCode == WallpaperPickerDelegate.SHOW_CATEGORY_REQUEST_CODE
                && resultCode == Activity.RESULT_OK) {
            if (mDelegate.getFormFactor() == FormFactorChecker.FORM_FACTOR_DESKTOP) {
                Uri imageUri = (data == null) ? null : data.getData();
                if (imageUri != null) {
                    // User selected an image from the system picker, so launch the preview for that
                    // image.
                    ImageWallpaperInfo imageWallpaper = new ImageWallpaperInfo(imageUri);
                    setCustomPhotoWallpaper(imageWallpaper);
                    return;
                }
            }
        }
        if (mDelegate.handleActivityResult(requestCode, resultCode, data)) {
            finishActivityWithResultOk();
        }
    }

    /**
     * Shows the view-only preview activity for the given wallpaper.
     */
    public void showViewOnlyPreview(WallpaperInfo wallpaperInfo, boolean isViewAsHome) {
        mDelegate.showViewOnlyPreview(wallpaperInfo, isViewAsHome);
    }

    @Override
    public void show(String collectionId) {
        mDelegate.show(collectionId);
    }

    @Override
    public void fetchCategories() {
        mDelegate.initialize(!mDelegate.getCategoryProvider().isCategoriesFetched());
    }

    @Override
    public void cleanUp() {
        mDelegate.cleanUp();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private void reselectLastTab() {
        TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

        // In the offline case, "My photos" could be the only category. Thus we need this check --
        // to ensure that we don't try to select the "previously selected" category which was -1.
        if (mLastSelectedCategoryTabIndex > -1) {
            Tab tabToSelect = tabLayout.getTabAt(
                    mLastSelectedCategoryTabIndex);
            if (((Category) tabToSelect.getTag()).isEnumerable()) {
                tabToSelect.select();
            }
        }
    }

    private void showCategoryDesktop(String collectionId) {
        Category category = mDelegate.findCategoryForCollectionId(collectionId);
        if (category == null) {
            return;
        }

        if (category.isEnumerable()) {
            // Replace contained IndividualPickerFragment with a new instance for the given category.
            final FragmentManager fm = getSupportFragmentManager();
            Fragment fragment = fm.findFragmentById(R.id.fragment_container);
            if (fragment != null) {
                fm.beginTransaction()
                        .remove(fragment)
                        .commit();
            }
            Injector injector = InjectorProvider.getInjector();
            IndividualPickerFragment newFragment = injector.getIndividualPickerFragment(
                    collectionId);
            fm.beginTransaction()
                    .add(R.id.fragment_container, newFragment)
                    .commit();
            newFragment.setCurrentWallpaperBottomSheetPresenter(this);
            newFragment.setWallpapersUiContainer(this);
        } else {
            category.show(this, mDelegate.getPickerIntentFactory(),
                    WallpaperPickerDelegate.SHOW_CATEGORY_REQUEST_CODE);

            // Need to select the tab here in case we are coming back from a "My photos" in which case
            // the tab would have been set to "My photos" while viewing a regular image category.
            reselectLastTab();
        }
    }

    private void finishActivityWithResultOk() {
        overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
        setResult(Activity.RESULT_OK);
        finish();
    }

    @Override
    public void setCurrentWallpapersExpanded(boolean expanded) {
        final BottomSheetBehavior<LinearLayout> bottomSheetBehavior =
                BottomSheetBehavior.from(mBottomSheet);
        bottomSheetBehavior.setState(
                expanded ? BottomSheetBehavior.STATE_EXPANDED
                        : BottomSheetBehavior.STATE_COLLAPSED);
    }

    @Override
    public void doneFetchingCategories() {
        populateCategoryTabs(mLastSelectedCategoryTabIndex);
    }

    @Override
    public void onWallpapersReady() {
        setDesktopLoading(false);
        setCurrentWallpapersExpanded(true);
    }

    @Override
    public MyPhotosStarter getMyPhotosStarter() {
        return this;
    }

    @Override
    public void onClickTryAgain(@Destination int unused) {
        // Retry the set wallpaper operation with the default center-crop setting.
        if (mPendingSetWallpaperInfo != null) {
            setCustomPhotoWallpaper(mPendingSetWallpaperInfo);
        }
    }

    /**
     * Sets the provides wallpaper to the device with center-cropped and scaled to fit the device's
     * default display.
     */
    private void setCustomPhotoWallpaper(final WallpaperInfo wallpaper) {
        // Save this WallpaperInfo so we can retry this operation later if it fails.
        mPendingSetWallpaperInfo = wallpaper;

        showSettingWallpaperProgressDialog();

        mWallpaperPersister.setIndividualWallpaperWithPosition(this, wallpaper,
                WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP, new SetWallpaperCallback() {
                    @Override
                    public void onSuccess(WallpaperInfo wallpaperInfo) {
                        dismissSettingWallpaperProgressDialog();
                        refreshCurrentWallpapers(null /* refreshListener */);

                        mDelegate.getPreferences().setPendingWallpaperSetStatus(
                                WallpaperPreferences.WALLPAPER_SET_NOT_PENDING);
                        mUserEventLogger.logWallpaperSet(
                                wallpaper.getCollectionId(getApplicationContext()),
                                wallpaper.getWallpaperId());
                        mUserEventLogger.logWallpaperSetResult(UserEventLogger.WALLPAPER_SET_RESULT_SUCCESS);

                        // The user may have closed the activity before the set wallpaper operation completed.
                        if (isDestroyed()) {
                            return;
                        }

                        // Show the wallpaper crop option selector and bind click event handlers.
                        mWallpaperPositionOptions.setVisibility(View.VISIBLE);

                        mWasCustomPhotoWallpaperSet = true;
                        mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP;

                        initializeWallpaperPositionOptionClickHandlers(wallpaper);
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        dismissSettingWallpaperProgressDialog();
                        showSetWallpaperErrorDialog();

                        mDelegate.getPreferences().setPendingWallpaperSetStatus(
                                WallpaperPreferences.WALLPAPER_SET_NOT_PENDING);
                        mUserEventLogger.logWallpaperSetResult(
                                UserEventLogger.WALLPAPER_SET_RESULT_FAILURE);
                        @WallpaperSetFailureReason int failureReason = ThrowableAnalyzer.isOOM(throwable)
                                ? UserEventLogger.WALLPAPER_SET_FAILURE_REASON_OOM
                                : UserEventLogger.WALLPAPER_SET_FAILURE_REASON_OTHER;
                        mUserEventLogger.logWallpaperSetFailureReason(failureReason);
                        Log.e(TAG, "Unable to set wallpaper from 'my photos'.");
                    }
                });
    }

    /**
     * Initializes the wallpaper position button click handlers to change the way the provided
     * wallpaper is set to the device.
     */
    private void initializeWallpaperPositionOptionClickHandlers(final WallpaperInfo wallpaperInfo) {
        Button centerCropOptionBtn = (Button) findViewById(R.id.wallpaper_position_option_center_crop);
        Button stretchOptionBtn = (Button) findViewById(R.id.wallpaper_position_option_stretched);
        Button centerOptionBtn = (Button) findViewById(R.id.wallpaper_position_option_center);

        // The "center crop" wallpaper position button is selected by default.
        setCenterCropWallpaperPositionButtonSelected(centerCropOptionBtn, true /* isSelected */);
        centerCropOptionBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mWallpaperPersister.setIndividualWallpaperWithPosition(TopLevelPickerActivity.this,
                        wallpaperInfo, WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP,
                        new SetWallpaperCallback() {
                            @Override
                            public void onSuccess(WallpaperInfo wallpaperInfo) {
                                // The user may have closed the activity before the set wallpaper operation
                                // completed.
                                if (isDestroyed()) {
                                    return;
                                }

                                refreshCurrentWallpapers(null /* refreshListener */);

                                setCenterCropWallpaperPositionButtonSelected(
                                        centerCropOptionBtn, true /* isSelected */);
                                setCenterWallpaperPositionButtonSelected(centerOptionBtn, false /* isSelected */);
                                setStretchWallpaperPositionButtonSelected(stretchOptionBtn, false /* isSelected */);

                                mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_CENTER_CROP;
                            }

                            @Override
                            public void onError(@Nullable Throwable throwable) {
                                // no-op
                            }
                        });
            }
        });

        // "Stretch" is not selected by default.
        setStretchWallpaperPositionButtonSelected(stretchOptionBtn, false /* isSelected */);
        stretchOptionBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mWallpaperPersister.setIndividualWallpaperWithPosition(TopLevelPickerActivity.this,
                        wallpaperInfo, WallpaperPersister.WALLPAPER_POSITION_STRETCH,
                        new SetWallpaperCallback() {
                            @Override
                            public void onSuccess(WallpaperInfo wallpaperInfo) {
                                // The user may have closed the activity before the set wallpaper operation
                                // completed.
                                if (isDestroyed()) {
                                    return;
                                }

                                refreshCurrentWallpapers(null /* refreshListener */);

                                setStretchWallpaperPositionButtonSelected(stretchOptionBtn, true /* isSelected */);
                                setCenterCropWallpaperPositionButtonSelected(
                                        centerCropOptionBtn, false /* isSelected */);
                                setCenterWallpaperPositionButtonSelected(centerOptionBtn, false /* isSelected */);

                                mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_STRETCH;
                            }

                            @Override
                            public void onError(@Nullable Throwable throwable) {
                                // no-op
                            }
                        });
            }
        });

        // "Center" is not selected by default.
        setCenterWallpaperPositionButtonSelected(centerOptionBtn, false /* isSelected */);
        centerOptionBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mWallpaperPersister.setIndividualWallpaperWithPosition(TopLevelPickerActivity.this,
                        wallpaperInfo, WallpaperPersister.WALLPAPER_POSITION_CENTER,
                        new SetWallpaperCallback() {
                            @Override
                            public void onSuccess(WallpaperInfo wallpaperInfo) {
                                // The user may have closed the activity before the set wallpaper operation
                                // completed.
                                if (isDestroyed()) {
                                    return;
                                }

                                refreshCurrentWallpapers(null /* refreshListener */);

                                setCenterWallpaperPositionButtonSelected(centerOptionBtn, true /* isSelected */);
                                setCenterCropWallpaperPositionButtonSelected(
                                        centerCropOptionBtn, false /* isSelected */);
                                setStretchWallpaperPositionButtonSelected(stretchOptionBtn, false /* isSelected */);

                                mCustomPhotoWallpaperPosition = WallpaperPersister.WALLPAPER_POSITION_CENTER;
                            }

                            @Override
                            public void onError(@Nullable Throwable throwable) {
                                // no-op
                            }
                        });
            }
        });
    }

    private void setCenterWallpaperPositionButtonSelected(Button button, boolean isSelected) {
        int drawableId = isSelected ? R.drawable.center_blue : R.drawable.center_grey;
        ButtonDrawableSetterCompat.setDrawableToButtonStart(button, getDrawable(drawableId));
        button.setTextColor(getTextColorForWallpaperPositionButton(isSelected));
    }

    private void setCenterCropWallpaperPositionButtonSelected(Button button, boolean isSelected) {
        int drawableId = isSelected ? R.drawable.center_crop_blue : R.drawable.center_crop_grey;
        ButtonDrawableSetterCompat.setDrawableToButtonStart(button, getDrawable(drawableId));
        button.setTextColor(getTextColorForWallpaperPositionButton(isSelected));
    }

    private void setStretchWallpaperPositionButtonSelected(Button button, boolean isSelected) {
        int drawableId = isSelected ? R.drawable.stretch_blue : R.drawable.stretch_grey;
        ButtonDrawableSetterCompat.setDrawableToButtonStart(button, getDrawable(drawableId));
        button.setTextColor(getTextColorForWallpaperPositionButton(isSelected));
    }

    private void showSettingWallpaperProgressDialog() {
        // ProgressDialog endlessly updates the UI thread, keeping it from going idle which
        // therefore causes Espresso to hang once the dialog is shown.
        if (!mTestingMode) {
            int themeResId;
            if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
                themeResId = R.style.ProgressDialogThemePreL;
            } else {
                themeResId = R.style.LightDialogTheme;
            }
            mSetWallpaperProgressDialog = new ProgressDialog(this, themeResId);
            mSetWallpaperProgressDialog.setTitle(null);
            mSetWallpaperProgressDialog.setMessage(
                    getResources().getString(R.string.set_wallpaper_progress_message));
            mSetWallpaperProgressDialog.setIndeterminate(true);
            mSetWallpaperProgressDialog.show();
        }
    }

    private void dismissSettingWallpaperProgressDialog() {
        if (mSetWallpaperProgressDialog != null) {
            mSetWallpaperProgressDialog.dismiss();
        }
    }

    private void showSetWallpaperErrorDialog() {
        SetWallpaperErrorDialogFragment dialogFragment = SetWallpaperErrorDialogFragment.newInstance(
                R.string.set_wallpaper_error_message, WallpaperPersister.DEST_BOTH);

        if (isSafeToCommitFragmentTransaction()) {
            dialogFragment.show(getSupportFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
        } else {
            mStagedSetWallpaperErrorDialogFragment = dialogFragment;
        }
    }

    @Override
    public void onUpArrowPressed() {
        onBackPressed();
    }

    @Override
    public boolean isUpArrowSupported() {
        return !ActivityUtils.isSUWMode(getBaseContext());
    }

    private interface AssetReceiver {
        void onAssetReceived(Asset asset);
    }

    /**
     * An AsyncTask for asynchronously fetching the thumbnail asset for a given WallpaperInfo.
     * Used to work around expensive method call to WallpaperManager#getWallpaperFile made from the
     * CurrentWallpaperInfoVN getAsset() method.
     */
    private static class FetchThumbAssetTask extends AsyncTask<Void, Void, Asset> {
        private Context mAppContext;
        private WallpaperInfo mWallpaperInfo;
        private AssetReceiver mReceiver;

        public FetchThumbAssetTask(Context appContext, WallpaperInfo wallpaperInfo,
                                   AssetReceiver receiver) {
            mAppContext = appContext;
            mWallpaperInfo = wallpaperInfo;
            mReceiver = receiver;
        }

        @Override
        protected Asset doInBackground(Void... params) {
            return mWallpaperInfo.getThumbAsset(mAppContext);
        }

        @Override
        protected void onPostExecute(Asset thumbAsset) {
            mReceiver.onAssetReceived(thumbAsset);
        }
    }
}
