/*
 * Copyright (C) 2018 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.Manifest.permission;
import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.service.wallpaper.WallpaperService;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;

import com.android.wallpaper.R;
import com.android.wallpaper.compat.WallpaperManagerCompat;
import com.android.wallpaper.model.Category;
import com.android.wallpaper.model.CategoryProvider;
import com.android.wallpaper.model.CategoryReceiver;
import com.android.wallpaper.model.ImageWallpaperInfo;
import com.android.wallpaper.model.InlinePreviewIntentFactory;
import com.android.wallpaper.model.WallpaperInfo;
import com.android.wallpaper.module.Injector;
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.module.PackageStatusNotifier;
import com.android.wallpaper.module.PackageStatusNotifier.PackageStatus;
import com.android.wallpaper.module.WallpaperPersister;
import com.android.wallpaper.module.WallpaperPreferences;
import com.android.wallpaper.picker.PreviewActivity.PreviewActivityIntentFactory;
import com.android.wallpaper.picker.ViewOnlyPreviewActivity.ViewOnlyPreviewActivityIntentFactory;
import com.android.wallpaper.picker.WallpaperDisabledFragment.WallpaperSupportLevel;

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

/**
 * Implements all the logic for handling a WallpaperPicker container Activity.
 * @see CustomizationPickerActivity for usage details.
 */
public class WallpaperPickerDelegate implements MyPhotosStarter {

    private final FragmentActivity mActivity;
    private final WallpapersUiContainer mContainer;
    public static final int SHOW_CATEGORY_REQUEST_CODE = 0;
    public static final int PREVIEW_WALLPAPER_REQUEST_CODE = 1;
    public static final int VIEW_ONLY_PREVIEW_WALLPAPER_REQUEST_CODE = 2;
    public static final int READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 3;
    public static final int PREVIEW_LIVE_WALLPAPER_REQUEST_CODE = 4;
    public static final String IS_LIVE_WALLPAPER = "isLiveWallpaper";

    private InlinePreviewIntentFactory mPreviewIntentFactory;
    private InlinePreviewIntentFactory mViewOnlyPreviewIntentFactory;

    private WallpaperPreferences mPreferences;
    private PackageStatusNotifier mPackageStatusNotifier;

    private List<PermissionChangedListener> mPermissionChangedListeners;
    private PackageStatusNotifier.Listener mLiveWallpaperStatusListener;
    private PackageStatusNotifier.Listener mThirdPartyStatusListener;
    private PackageStatusNotifier.Listener mDownloadableWallpaperStatusListener;
    private String mDownloadableIntentAction;
    private CategoryProvider mCategoryProvider;
    private WallpaperPersister mWallpaperPersister;
    private static final String READ_IMAGE_PERMISSION = permission.READ_MEDIA_IMAGES;

    public WallpaperPickerDelegate(WallpapersUiContainer container, FragmentActivity activity,
            Injector injector) {
        mContainer = container;
        mActivity = activity;
        mPreviewIntentFactory = new PreviewActivityIntentFactory();
        mViewOnlyPreviewIntentFactory =
                new ViewOnlyPreviewActivityIntentFactory();

        mCategoryProvider = injector.getCategoryProvider(activity);
        mPreferences = injector.getPreferences(activity);

        mPackageStatusNotifier = injector.getPackageStatusNotifier(activity);
        mWallpaperPersister = injector.getWallpaperPersister(activity);

        mPermissionChangedListeners = new ArrayList<>();
        mDownloadableIntentAction = injector.getDownloadableIntentAction();
    }

    public void initialize(boolean forceCategoryRefresh) {
        populateCategories(forceCategoryRefresh);
        mLiveWallpaperStatusListener = this::updateLiveWallpapersCategories;
        mThirdPartyStatusListener = this::updateThirdPartyCategories;
        mPackageStatusNotifier.addListener(
                mLiveWallpaperStatusListener,
                WallpaperService.SERVICE_INTERFACE);
        mPackageStatusNotifier.addListener(mThirdPartyStatusListener, Intent.ACTION_SET_WALLPAPER);
        if (mDownloadableIntentAction != null) {
            mDownloadableWallpaperStatusListener = (packageName, status) -> {
                if (status != PackageStatusNotifier.PackageStatus.REMOVED) {
                    populateCategories(/* forceRefresh= */ true);
                }
            };
            mPackageStatusNotifier.addListener(
                    mDownloadableWallpaperStatusListener, mDownloadableIntentAction);
        }
    }

    @Override
    public void requestCustomPhotoPicker(PermissionChangedListener listener) {
        if (!isReadExternalStoragePermissionGranted()) {
            PermissionChangedListener wrappedListener = new PermissionChangedListener() {
                @Override
                public void onPermissionsGranted() {
                    listener.onPermissionsGranted();
                    showCustomPhotoPicker();
                }

                @Override
                public void onPermissionsDenied(boolean dontAskAgain) {
                    listener.onPermissionsDenied(dontAskAgain);
                }
            };
            requestExternalStoragePermission(wrappedListener);

            return;
        }

        showCustomPhotoPicker();
    }

    /**
     * Requests to show the Android custom photo picker for the sake of picking a
     * photo to set as the device's wallpaper.
     */
    public void requestExternalStoragePermission(PermissionChangedListener listener) {
        mPermissionChangedListeners.add(listener);
        mActivity.requestPermissions(
                new String[]{READ_IMAGE_PERMISSION},
                READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
    }

    /**
     * Returns whether READ_MEDIA_IMAGES has been granted for the application.
     */
    public boolean isReadExternalStoragePermissionGranted() {
        return mActivity.getPackageManager().checkPermission(
                permission.READ_MEDIA_IMAGES,
                mActivity.getPackageName()) == PackageManager.PERMISSION_GRANTED;
    }

    private void showCustomPhotoPicker() {
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        mActivity.startActivityForResult(intent, SHOW_CATEGORY_REQUEST_CODE);
    }

    private void updateThirdPartyCategories(String packageName, @PackageStatus int status) {
        if (status == PackageStatus.ADDED) {
            mCategoryProvider.fetchCategories(new CategoryReceiver() {
                @Override
                public void onCategoryReceived(Category category) {
                    if (category.supportsThirdParty() && category.containsThirdParty(packageName)) {
                        addCategory(category, false);
                    }
                }

                @Override
                public void doneFetchingCategories() {
                    // Do nothing here.
                }
            }, true);
        } else if (status == PackageStatus.REMOVED) {
            Category oldCategory = findThirdPartyCategory(packageName);
            if (oldCategory != null) {
                mCategoryProvider.fetchCategories(new CategoryReceiver() {
                    @Override
                    public void onCategoryReceived(Category category) {
                        // Do nothing here
                    }

                    @Override
                    public void doneFetchingCategories() {
                        removeCategory(oldCategory);
                    }
                }, true);
            }
        } else {
            // CHANGED package, let's reload all categories as we could have more or fewer now
            populateCategories(/* forceRefresh= */ true);
        }
    }

    private Category findThirdPartyCategory(String packageName) {
        int size = mCategoryProvider.getSize();
        for (int i = 0; i < size; i++) {
            Category category = mCategoryProvider.getCategory(i);
            if (category.supportsThirdParty() && category.containsThirdParty(packageName)) {
                return category;
            }
        }
        return null;
    }

    private void updateLiveWallpapersCategories(String packageName,
            @PackageStatus int status) {
        String liveWallpaperCollectionId = mActivity.getString(
                R.string.live_wallpaper_collection_id);
        Category oldLiveWallpapersCategory = mCategoryProvider.getCategory(
                liveWallpaperCollectionId);
        if (status == PackageStatus.REMOVED
                && (oldLiveWallpapersCategory == null
                || !oldLiveWallpapersCategory.containsThirdParty(packageName))) {
            // If we're removing a wallpaper and the live category didn't contain it already,
            // there's nothing to do.
            return;
        }
        mCategoryProvider.fetchCategories(new CategoryReceiver() {
            @Override
            public void onCategoryReceived(Category category) {
                // Do nothing here
            }

            @Override
            public void doneFetchingCategories() {
                Category liveWallpapersCategory =
                        mCategoryProvider.getCategory(liveWallpaperCollectionId);
                if (liveWallpapersCategory == null) {
                    // There are no more 3rd party live wallpapers, so the Category is gone.
                    removeCategory(oldLiveWallpapersCategory);
                } else {
                    if (oldLiveWallpapersCategory != null) {
                        updateCategory(liveWallpapersCategory);
                    } else {
                        addCategory(liveWallpapersCategory, false);
                    }
                }
            }
        }, true);
    }

    /**
     * Fetch the wallpaper categories but don't call any callbacks on the result, just so that
     * they're cached when loading later.
     */
    public void prefetchCategories() {
        boolean forceRefresh = mCategoryProvider.resetIfNeeded();
        mCategoryProvider.fetchCategories(new CategoryReceiver() {
            @Override
            public void onCategoryReceived(Category category) {
                // Do nothing
            }

            @Override
            public void doneFetchingCategories() {
                // Do nothing
            }
        }, forceRefresh);
    }

    /**
     * Populates the categories appropriately.
     *
     * @param forceRefresh        Whether to force a refresh of categories from the
     *                            CategoryProvider. True if
     *                            on first launch.
     */
    public void populateCategories(boolean forceRefresh) {

        final CategorySelectorFragment categorySelectorFragment = getCategorySelectorFragment();

        if (forceRefresh && categorySelectorFragment != null) {
            categorySelectorFragment.clearCategories();
        }

        mCategoryProvider.fetchCategories(new CategoryReceiver() {
            @Override
            public void onCategoryReceived(Category category) {
                addCategory(category, true);
            }

            @Override
            public void doneFetchingCategories() {
                notifyDoneFetchingCategories();
            }
        }, forceRefresh);
    }

    private void notifyDoneFetchingCategories() {
        CategorySelectorFragment categorySelectorFragment = getCategorySelectorFragment();
        if (categorySelectorFragment != null) {
            categorySelectorFragment.doneFetchingCategories();
        }
    }

    public void addCategory(Category category, boolean fetchingAll) {
        CategorySelectorFragment categorySelectorFragment = getCategorySelectorFragment();
        if (categorySelectorFragment != null) {
            categorySelectorFragment.addCategory(category, fetchingAll);
        }
    }

    public void removeCategory(Category category) {
        CategorySelectorFragment categorySelectorFragment = getCategorySelectorFragment();
        if (categorySelectorFragment != null) {
            categorySelectorFragment.removeCategory(category);
        }
    }

    public void updateCategory(Category category) {
        CategorySelectorFragment categorySelectorFragment = getCategorySelectorFragment();
        if (categorySelectorFragment != null) {
            categorySelectorFragment.updateCategory(category);
        }
    }

    @Nullable
    private CategorySelectorFragment getCategorySelectorFragment() {
        return mContainer.getCategorySelectorFragment();
    }

    /**
     * Shows the view-only preview activity for the given wallpaper.
     */
    public void showViewOnlyPreview(WallpaperInfo wallpaperInfo, boolean isViewAsHome) {
        ((ViewOnlyPreviewActivityIntentFactory) mViewOnlyPreviewIntentFactory).setAsHomePreview(
                /* isHomeAndLockPreviews= */ true, isViewAsHome);
        wallpaperInfo.showPreview(
                mActivity, mViewOnlyPreviewIntentFactory,
                VIEW_ONLY_PREVIEW_WALLPAPER_REQUEST_CODE);
    }

    /**
     * Shows the picker activity for the given category.
     */
    public void show(String collectionId) {
        Category category = findCategoryForCollectionId(collectionId);
        if (category == null) {
            return;
        }
        category.show(mActivity, SHOW_CATEGORY_REQUEST_CODE);
    }

    @Nullable
    public Category findCategoryForCollectionId(String collectionId) {
        return mCategoryProvider.getCategory(collectionId);
    }

    @WallpaperSupportLevel
    public int getWallpaperSupportLevel() {
        WallpaperManager wallpaperManager = WallpaperManager.getInstance(mActivity);

        if (VERSION.SDK_INT >= VERSION_CODES.N) {
            if (wallpaperManager.isWallpaperSupported()) {
                return wallpaperManager.isSetWallpaperAllowed()
                        ? WallpaperDisabledFragment.SUPPORTED_CAN_SET
                        : WallpaperDisabledFragment.NOT_SUPPORTED_BLOCKED_BY_ADMIN;
            }
            return WallpaperDisabledFragment.NOT_SUPPORTED_BY_DEVICE;
        } else if (VERSION.SDK_INT >= VERSION_CODES.M) {
            return wallpaperManager.isWallpaperSupported()
                    ? WallpaperDisabledFragment.SUPPORTED_CAN_SET
                    : WallpaperDisabledFragment.NOT_SUPPORTED_BY_DEVICE;
        } else {
            WallpaperManagerCompat wallpaperManagerCompat =
                    InjectorProvider.getInjector().getWallpaperManagerCompat(
                            mActivity);
            boolean isSupported = wallpaperManagerCompat.getDrawable() != null;
            wallpaperManager.forgetLoadedWallpaper();
            return isSupported ? WallpaperDisabledFragment.SUPPORTED_CAN_SET
                    : WallpaperDisabledFragment.NOT_SUPPORTED_BY_DEVICE;
        }
    }

    public InlinePreviewIntentFactory getPreviewIntentFactory() {
        return mPreviewIntentFactory;
    }

    public WallpaperPreferences getPreferences() {
        return mPreferences;
    }

    public List<PermissionChangedListener> getPermissionChangedListeners() {
        return mPermissionChangedListeners;
    }

    public CategoryProvider getCategoryProvider() {
        return mCategoryProvider;
    }

    /**
     * Call when the owner activity is destroyed to clean up listeners.
     */
    public void cleanUp() {
        if (mPackageStatusNotifier != null) {
            mPackageStatusNotifier.removeListener(mLiveWallpaperStatusListener);
            mPackageStatusNotifier.removeListener(mThirdPartyStatusListener);
            mPackageStatusNotifier.removeListener(mDownloadableWallpaperStatusListener);
        }
    }

    /**
     * Call from the Activity's onRequestPermissionsResult callback to handle permission request
     * relevant to wallpapers (ie, READ_MEDIA_IMAGES)
     * @see androidx.fragment.app.FragmentActivity#onRequestPermissionsResult(int, String[], int[])
     */
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        if (requestCode == WallpaperPickerDelegate.READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE
                && permissions.length > 0
                && permissions[0].equals(READ_IMAGE_PERMISSION)
                && grantResults.length > 0) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                for (PermissionChangedListener listener : getPermissionChangedListeners()) {
                    listener.onPermissionsGranted();
                }
            } else if (!mActivity.shouldShowRequestPermissionRationale(READ_IMAGE_PERMISSION)) {
                for (PermissionChangedListener listener : getPermissionChangedListeners()) {
                    listener.onPermissionsDenied(true /* dontAskAgain */);
                }
            } else {
                for (PermissionChangedListener listener :getPermissionChangedListeners()) {
                    listener.onPermissionsDenied(false /* dontAskAgain */);
                }
            }
        }
       getPermissionChangedListeners().clear();
    }

    /**
     * To be called from an Activity's onActivityResult method.
     * Checks the result for ones that are handled by this delegate
     * @return true if the intent was handled and calling Activity needs to finish with result
     * OK, false otherwise.
     */
    public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != Activity.RESULT_OK) {
            return false;
        }

        switch (requestCode) {
            case SHOW_CATEGORY_REQUEST_CODE:
                Uri imageUri = (data == null) ? null : data.getData();
                if (imageUri == null) {
                    // User finished viewing a category without any data, which implies that the
                    // user previewed and selected a wallpaper in-app, so finish this activity.
                    return true;
                }

                // User selected an image from the system picker, so launch the preview for that
                // image.
                ImageWallpaperInfo imageWallpaper = new ImageWallpaperInfo(imageUri);

                mWallpaperPersister.setWallpaperInfoInPreview(imageWallpaper);
                imageWallpaper.showPreview(mActivity, getPreviewIntentFactory(),
                        PREVIEW_WALLPAPER_REQUEST_CODE);
                return false;
            case PREVIEW_LIVE_WALLPAPER_REQUEST_CODE:
                mWallpaperPersister.onLiveWallpaperSet();
                populateCategories(/* forceRefresh= */ true);
                return true;
            case VIEW_ONLY_PREVIEW_WALLPAPER_REQUEST_CODE:
                return true;
            case PREVIEW_WALLPAPER_REQUEST_CODE:
                // User previewed and selected a wallpaper, so finish this activity.
                if (data != null && data.getBooleanExtra(IS_LIVE_WALLPAPER, false)) {
                    mWallpaperPersister.onLiveWallpaperSet();
                    populateCategories(/* forceRefresh= */ true);
                }
                return true;
            default:
                return false;
        }
    }
}
