/*
 * 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.wallpaper.picker;

import static com.android.wallpaper.util.ActivityUtils.isSUWMode;
import static com.android.wallpaper.util.ActivityUtils.isWallpaperOnlyMode;
import static com.android.wallpaper.util.ActivityUtils.startActivityForResultSafely;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.WindowCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;

import com.android.wallpaper.R;
import com.android.wallpaper.model.Category;
import com.android.wallpaper.model.PermissionRequester;
import com.android.wallpaper.model.WallpaperCategory;
import com.android.wallpaper.model.WallpaperInfo;
import com.android.wallpaper.model.WallpaperPreviewNavigator;
import com.android.wallpaper.module.DailyLoggingAlarmScheduler;
import com.android.wallpaper.module.Injector;
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.module.LargeScreenMultiPanesChecker;
import com.android.wallpaper.module.MultiPanesChecker;
import com.android.wallpaper.module.NetworkStatusNotifier;
import com.android.wallpaper.module.NetworkStatusNotifier.NetworkStatus;
import com.android.wallpaper.module.UserEventLogger;
import com.android.wallpaper.picker.AppbarFragment.AppbarFragmentHost;
import com.android.wallpaper.picker.CategorySelectorFragment.CategorySelectorFragmentHost;
import com.android.wallpaper.picker.MyPhotosStarter.PermissionChangedListener;
import com.android.wallpaper.picker.individual.IndividualPickerFragment.IndividualPickerFragmentHost;
import com.android.wallpaper.util.ActivityUtils;
import com.android.wallpaper.util.DeepLinkUtils;
import com.android.wallpaper.util.LaunchUtils;
import com.android.wallpaper.widget.BottomActionBar;
import com.android.wallpaper.widget.BottomActionBar.BottomActionBarHost;

/**
 *  Main Activity allowing containing view sections for the user to switch between the different
 *  Fragments providing customization options.
 */
public class CustomizationPickerActivity extends FragmentActivity implements AppbarFragmentHost,
        WallpapersUiContainer, BottomActionBarHost, FragmentTransactionChecker,
        PermissionRequester, CategorySelectorFragmentHost, IndividualPickerFragmentHost,
        WallpaperPreviewNavigator {

    private static final String TAG = "CustomizationPickerActivity";

    private WallpaperPickerDelegate mDelegate;
    private UserEventLogger mUserEventLogger;
    private NetworkStatusNotifier mNetworkStatusNotifier;
    private NetworkStatusNotifier.Listener mNetworkStatusListener;
    @NetworkStatus private int mNetworkStatus;

    private BottomActionBar mBottomActionBar;
    private boolean mIsSafeToCommitFragmentTransaction;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        Injector injector = InjectorProvider.getInjector();
        mDelegate = new WallpaperPickerDelegate(this, this, injector);
        mUserEventLogger = injector.getUserEventLogger(this);
        mNetworkStatusNotifier = injector.getNetworkStatusNotifier(this);
        mNetworkStatus = mNetworkStatusNotifier.getNetworkStatus();

        // Restore this Activity's state before restoring contained Fragments state.
        super.onCreate(savedInstanceState);
        // Trampoline for the two panes
        final MultiPanesChecker mMultiPanesChecker = new LargeScreenMultiPanesChecker();
        if (mMultiPanesChecker.isMultiPanesEnabled(this)) {
            Intent intent = getIntent();
            if (!ActivityUtils.isLaunchedFromSettingsTrampoline(intent)
                    && !ActivityUtils.isLaunchedFromSettingsRelated(intent)) {
                startActivityForResultSafely(this,
                        mMultiPanesChecker.getMultiPanesIntent(intent), /* requestCode= */ 0);
                finish();
            }
        }

        setContentView(R.layout.activity_customization_picker);
        mBottomActionBar = findViewById(R.id.bottom_actionbar);

        // See go/pdr-edge-to-edge-guide.
        WindowCompat.setDecorFitsSystemWindows(getWindow(), isSUWMode(this));

        Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
        if (fragment == null) {
            // App launch specific logic: log the "app launch source" event.
            if (getIntent() != null) {
                mUserEventLogger.logAppLaunched(getIntent());
            }
            injector.getPreferences(this).incrementAppLaunched();
            DailyLoggingAlarmScheduler.setAlarm(getApplicationContext());

            // Switch to the target fragment.
            switchFragment(isWallpaperOnlyMode(getIntent())
                    ? new WallpaperOnlyFragment()
                    : new CustomizationPickerFragment());
        }

        // Deep link case
        Intent intent = getIntent();
        String deepLinkCollectionId = DeepLinkUtils.getCollectionId(intent);
        if (!TextUtils.isEmpty(deepLinkCollectionId)) {
            switchFragmentWithBackStack(new CategorySelectorFragment());
            switchFragmentWithBackStack(InjectorProvider.getInjector().getIndividualPickerFragment(
                    deepLinkCollectionId));
            intent.setData(null);
        }
        mDelegate.prefetchCategories();
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (mNetworkStatusListener == null) {
            mNetworkStatusListener = status -> {
                if (status == mNetworkStatus) {
                    return;
                }
                Log.i(TAG, "Network status changes, refresh wallpaper categories.");
                mNetworkStatus = status;
                mDelegate.initialize(/* forceCategoryRefresh= */ true);
            };
            // Upon registering a listener, the onNetworkChanged method is immediately called with
            // the initial network status.
            mNetworkStatusNotifier.registerListener(mNetworkStatusListener);
        }
    }

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

        mUserEventLogger.logResumed(provisioned, wallpaperOnly);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mIsSafeToCommitFragmentTransaction = false;
    }

    @Override
    protected void onStop() {
        mUserEventLogger.logStopped();
        if (mNetworkStatusListener != null) {
            mNetworkStatusNotifier.unregisterListener(mNetworkStatusListener);
            mNetworkStatusListener = null;
        }
        super.onStop();
    }

    @Override
    public void onBackPressed() {
        Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
        if (fragment instanceof BottomActionBarFragment
                && ((BottomActionBarFragment) fragment).onBackPressed()) {
            return;
        }

        if (getSupportFragmentManager().popBackStackImmediate()) {
            return;
        }
        if (moveTaskToBack(false)) {
            return;
        }
        super.onBackPressed();
    }

    private void switchFragment(Fragment fragment) {
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.fragment_container, fragment)
                .commitNow();
    }

    private void switchFragmentWithBackStack(Fragment fragment) {
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.fragment_container, fragment)
                .addToBackStack(null)
                .commit();
        getSupportFragmentManager().executePendingTransactions();
    }


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

    @Override
    public void showViewOnlyPreview(WallpaperInfo wallpaperInfo, boolean isViewAsHome) {
        mDelegate.showViewOnlyPreview(wallpaperInfo, isViewAsHome);
    }

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

    @Override
    public void show(Category category) {
        if (!(category instanceof WallpaperCategory)) {
            mDelegate.show(category.getCollectionId());
            return;
        }
        switchFragmentWithBackStack(InjectorProvider.getInjector().getIndividualPickerFragment(
                category.getCollectionId()));
    }

    @Override
    public boolean isHostToolbarShown() {
        return false;
    }

    @Override
    public void setToolbarTitle(CharSequence title) {

    }

    @Override
    public void setToolbarMenu(int menuResId) {

    }

    @Override
    public void removeToolbarMenu() {

    }

    @Override
    public void moveToPreviousFragment() {
        getSupportFragmentManager().popBackStack();
    }

    @Override
    public void fetchCategories() {
        mDelegate.initialize(mDelegate.getCategoryProvider().shouldForceReload(this));
    }

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

    @Override
    public void onWallpapersReady() {

    }

    @Nullable
    @Override
    public CategorySelectorFragment getCategorySelectorFragment() {
        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragment_container);
        if (fragment instanceof CategorySelectorFragment) {
            return (CategorySelectorFragment) fragment;
        } else {
            return null;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void doneFetchingCategories() {

    }

    @SuppressWarnings("MissingSuperCall") // TODO: Fix me
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (mDelegate.handleActivityResult(requestCode, resultCode, data)) {
            if (isSUWMode(this)) {
                finishActivityForSUW();
            } else {
                finishActivityWithResultOk();
            }
        }
    }

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

        // Go back to launcher home
        LaunchUtils.launchHome(this);
    }

    private void finishActivityForSUW() {
        overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
        // Return RESULT_CANCELED to make the "Change wallpaper" tile in SUW not be disabled.
        setResult(Activity.RESULT_CANCELED);
        finish();
    }

    @Override
    public BottomActionBar getBottomActionBar() {
        return mBottomActionBar;
    }

    @Override
    public boolean isSafeToCommitFragmentTransaction() {
        return mIsSafeToCommitFragmentTransaction;
    }

    @Override
    public void onUpArrowPressed() {
        // TODO(b/189166781): Remove interface AppbarFragmentHost#onUpArrowPressed.
        onBackPressed();
    }

    @Override
    public boolean isUpArrowSupported() {
        return !isSUWMode(this);
    }
}
