/*
 * Copyright (C) 2008 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.settings;

import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
import android.app.ActionBar;
import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.sysprop.VoldProperties;
import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnScrollChangeListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;

import androidx.annotation.VisibleForTesting;

import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.development.DevelopmentSettingsEnabler;

import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.template.FooterButton.ButtonType;
import com.google.android.setupdesign.GlifLayout;

import java.util.List;

/**
 * Confirm and execute a reset of the device to a clean "just out of the box"
 * state.  Multiple confirmations are required: first, a general "are you sure
 * you want to do this?" prompt, followed by a keyguard pattern trace if the user
 * has defined one, followed by a final strongly-worded "THIS WILL ERASE EVERYTHING
 * ON THE PHONE" prompt.  If at any time the phone is allowed to go to sleep, is
 * locked, et cetera, then the confirmation sequence is abandoned.
 *
 * This is the initial screen.
 */
public class MasterClear extends InstrumentedFragment implements OnGlobalLayoutListener {
    private static final String TAG = "MasterClear";

    @VisibleForTesting
    static final int KEYGUARD_REQUEST = 55;
    @VisibleForTesting
    static final int CREDENTIAL_CONFIRM_REQUEST = 56;

    private static final String KEY_SHOW_ESIM_RESET_CHECKBOX
            = "masterclear.allow_retain_esim_profiles_after_fdr";

    static final String ERASE_EXTERNAL_EXTRA = "erase_sd";
    static final String ERASE_ESIMS_EXTRA = "erase_esim";

    private View mContentView;
    @VisibleForTesting
    FooterButton mInitiateButton;
    private View mExternalStorageContainer;
    @VisibleForTesting
    CheckBox mExternalStorage;
    @VisibleForTesting
    View mEsimStorageContainer;
    @VisibleForTesting
    CheckBox mEsimStorage;
    @VisibleForTesting
    ScrollView mScrollView;

    @Override
    public void onGlobalLayout() {
        mInitiateButton.setEnabled(hasReachedBottom(mScrollView));
    }

    private void setUpActionBarAndTitle() {
        final Activity activity = getActivity();
        if (activity == null) {
            Log.e(TAG, "No activity attached, skipping setUpActionBarAndTitle");
            return;
        }
        final ActionBar actionBar = activity.getActionBar();
        if (actionBar == null) {
            Log.e(TAG, "No actionbar, skipping setUpActionBarAndTitle");
            return;
        }
        actionBar.hide();
        activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
    }

    /**
     * Keyguard validation is run using the standard {@link ConfirmLockPattern}
     * component as a subactivity
     *
     * @param request the request code to be returned once confirmation finishes
     * @return true if confirmation launched
     */
    private boolean runKeyguardConfirmation(int request) {
        Resources res = getActivity().getResources();
        return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
                request, res.getText(R.string.master_clear_short_title));
    }

    @VisibleForTesting
    boolean isValidRequestCode(int requestCode) {
        return !((requestCode != KEYGUARD_REQUEST) && (requestCode != CREDENTIAL_CONFIRM_REQUEST));
    }

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

    /*
     * Internal method that allows easy testing without dealing with super references.
     */
    @VisibleForTesting
    void onActivityResultInternal(int requestCode, int resultCode, Intent data) {
        if (!isValidRequestCode(requestCode)) {
            return;
        }

        if (resultCode != Activity.RESULT_OK) {
            establishInitialState();
            return;
        }

        Intent intent = null;
        // If returning from a Keyguard request, try to show an account confirmation request if
        // applciable.
        if (CREDENTIAL_CONFIRM_REQUEST != requestCode
                && (intent = getAccountConfirmationIntent()) != null) {
            showAccountCredentialConfirmation(intent);
        } else {
            showFinalConfirmation();
        }
    }

    @VisibleForTesting
    void showFinalConfirmation() {
        final Bundle args = new Bundle();
        args.putBoolean(ERASE_EXTERNAL_EXTRA, mExternalStorage.isChecked());
        args.putBoolean(ERASE_ESIMS_EXTRA, mEsimStorage.isChecked());
        new SubSettingLauncher(getContext())
                .setDestination(MasterClearConfirm.class.getName())
                .setArguments(args)
                .setTitleRes(R.string.master_clear_confirm_title)
                .setSourceMetricsCategory(getMetricsCategory())
                .launch();
    }

    @VisibleForTesting
    void showAccountCredentialConfirmation(Intent intent) {
        startActivityForResult(intent, CREDENTIAL_CONFIRM_REQUEST);
    }

    @VisibleForTesting
    Intent getAccountConfirmationIntent() {
        final Context context = getActivity();
        final String accountType = context.getString(R.string.account_type);
        final String packageName = context.getString(R.string.account_confirmation_package);
        final String className = context.getString(R.string.account_confirmation_class);
        if (TextUtils.isEmpty(accountType)
                || TextUtils.isEmpty(packageName)
                || TextUtils.isEmpty(className)) {
            Log.i(TAG, "Resources not set for account confirmation.");
            return null;
        }
        final AccountManager am = AccountManager.get(context);
        Account[] accounts = am.getAccountsByType(accountType);
        if (accounts != null && accounts.length > 0) {
            final Intent requestAccountConfirmation = new Intent()
                    .setPackage(packageName)
                    .setComponent(new ComponentName(packageName, className));
            // Check to make sure that the intent is supported.
            final PackageManager pm = context.getPackageManager();
            final ResolveInfo resolution = pm.resolveActivity(requestAccountConfirmation, 0);
            if (resolution != null
                    && resolution.activityInfo != null
                    && packageName.equals(resolution.activityInfo.packageName)) {
                // Note that we need to check the packagename to make sure that an Activity resolver
                // wasn't returned.
                return requestAccountConfirmation;
            } else {
                Log.i(TAG, "Unable to resolve Activity: " + packageName + "/" + className);
            }
        } else {
            Log.d(TAG, "No " + accountType + " accounts installed!");
        }
        return null;
    }

    /**
     * If the user clicks to begin the reset sequence, we next require a
     * keyguard confirmation if the user has currently enabled one.  If there
     * is no keyguard available, we simply go to the final confirmation prompt.
     *
     * If the user is in demo mode, route to the demo mode app for confirmation.
     */
    @VisibleForTesting
    protected final Button.OnClickListener mInitiateListener = new Button.OnClickListener() {

        public void onClick(View view) {
            final Context context = view.getContext();
            if (Utils.isDemoUser(context)) {
                final ComponentName componentName = Utils.getDeviceOwnerComponent(context);
                if (componentName != null) {
                    final Intent requestFactoryReset = new Intent()
                            .setPackage(componentName.getPackageName())
                            .setAction(Intent.ACTION_FACTORY_RESET);
                    context.startActivity(requestFactoryReset);
                }
                return;
            }

            if (runKeyguardConfirmation(KEYGUARD_REQUEST)) {
                return;
            }

            Intent intent = getAccountConfirmationIntent();
            if (intent != null) {
                showAccountCredentialConfirmation(intent);
            } else {
                showFinalConfirmation();
            }
        }
    };

    /**
     * In its initial state, the activity presents a button for the user to
     * click in order to initiate a confirmation sequence.  This method is
     * called from various other points in the code to reset the activity to
     * this base state.
     *
     * <p>Reinflating views from resources is expensive and prevents us from
     * caching widget pointers, so we use a single-inflate pattern:  we lazy-
     * inflate each view, caching all of the widget pointers we'll need at the
     * time, then simply reuse the inflated views directly whenever we need
     * to change contents.
     */
    @VisibleForTesting
    void establishInitialState() {
        setUpActionBarAndTitle();
        setUpInitiateButton();

        mExternalStorageContainer = mContentView.findViewById(R.id.erase_external_container);
        mExternalStorage = mContentView.findViewById(R.id.erase_external);
        mEsimStorageContainer = mContentView.findViewById(R.id.erase_esim_container);
        mEsimStorage = mContentView.findViewById(R.id.erase_esim);
        if (mScrollView != null) {
            mScrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
        mScrollView = mContentView.findViewById(R.id.master_clear_scrollview);

        /*
         * If the external storage is emulated, it will be erased with a factory
         * reset at any rate. There is no need to have a separate option until
         * we have a factory reset that only erases some directories and not
         * others. Likewise, if it's non-removable storage, it could potentially have been
         * encrypted, and will also need to be wiped.
         */
        boolean isExtStorageEmulated = Environment.isExternalStorageEmulated();
        if (isExtStorageEmulated
                || (!Environment.isExternalStorageRemovable() && isExtStorageEncrypted())) {
            mExternalStorageContainer.setVisibility(View.GONE);

            final View externalOption = mContentView.findViewById(R.id.erase_external_option_text);
            externalOption.setVisibility(View.GONE);

            final View externalAlsoErased = mContentView.findViewById(R.id.also_erases_external);
            externalAlsoErased.setVisibility(View.VISIBLE);

            // If it's not emulated, it is on a separate partition but it means we're doing
            // a force wipe due to encryption.
            mExternalStorage.setChecked(!isExtStorageEmulated);
        } else {
            mExternalStorageContainer.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    mExternalStorage.toggle();
                }
            });
        }

        if (showWipeEuicc()) {
            if (showWipeEuiccCheckbox()) {
                mEsimStorageContainer.setVisibility(View.VISIBLE);
                mEsimStorageContainer.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mEsimStorage.toggle();
                    }
                });
            } else {
                final View esimAlsoErased = mContentView.findViewById(R.id.also_erases_esim);
                esimAlsoErased.setVisibility(View.VISIBLE);

                final View noCancelMobilePlan = mContentView.findViewById(
                        R.id.no_cancel_mobile_plan);
                noCancelMobilePlan.setVisibility(View.VISIBLE);
                mEsimStorage.setChecked(true /* checked */);
            }
        } else {
            mEsimStorage.setChecked(false /* checked */);
        }

        final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
        loadAccountList(um);
        final StringBuffer contentDescription = new StringBuffer();
        final View masterClearContainer = mContentView.findViewById(R.id.master_clear_container);
        getContentDescription(masterClearContainer, contentDescription);
        masterClearContainer.setContentDescription(contentDescription);

        // Set the status of initiateButton based on scrollview
        mScrollView.setOnScrollChangeListener(new OnScrollChangeListener() {
            @Override
            public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX,
                    int oldScrollY) {
                if (v instanceof ScrollView && hasReachedBottom((ScrollView) v)) {
                    mInitiateButton.setEnabled(true);
                    mScrollView.setOnScrollChangeListener(null);
                }
            }
        });

        // Set the initial state of the initiateButton
        mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    /**
     * Whether to show strings indicating that the eUICC will be wiped.
     *
     * <p>We show the strings on any device which supports eUICC as long as the eUICC was ever
     * provisioned (that is, at least one profile was ever downloaded onto it).
     */
    @VisibleForTesting
    boolean showWipeEuicc() {
        Context context = getContext();
        if (!isEuiccEnabled(context)) {
            return false;
        }
        ContentResolver cr = context.getContentResolver();
        return Settings.Global.getInt(cr, Settings.Global.EUICC_PROVISIONED, 0) != 0
                || DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context);
    }

    @VisibleForTesting
    boolean showWipeEuiccCheckbox() {
        return SystemProperties
                .getBoolean(KEY_SHOW_ESIM_RESET_CHECKBOX, false /* def */);
    }

    @VisibleForTesting
    protected boolean isEuiccEnabled(Context context) {
        EuiccManager euiccManager = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
        return euiccManager.isEnabled();
    }

    @VisibleForTesting
    boolean hasReachedBottom(final ScrollView scrollView) {
        if (scrollView.getChildCount() < 1) {
            return true;
        }

        final View view = scrollView.getChildAt(0);
        final int diff = view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY());

        return diff <= 0;
    }

    private void setUpInitiateButton() {
        if (mInitiateButton != null) {
            return;
        }

        final GlifLayout layout = mContentView.findViewById(R.id.setup_wizard_layout);
        final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
        mixin.setPrimaryButton(
                new FooterButton.Builder(getActivity())
                        .setText(R.string.master_clear_button_text)
                        .setListener(mInitiateListener)
                        .setButtonType(ButtonType.OTHER)
                        .setTheme(R.style.SudGlifButton_Primary)
                        .build()
        );
        mInitiateButton = mixin.getPrimaryButton();
    }

    private void getContentDescription(View v, StringBuffer description) {
        if (v.getVisibility() != View.VISIBLE) {
            return;
        }
        if (v instanceof ViewGroup) {
            ViewGroup vGroup = (ViewGroup) v;
            for (int i = 0; i < vGroup.getChildCount(); i++) {
                View nextChild = vGroup.getChildAt(i);
                getContentDescription(nextChild, description);
            }
        } else if (v instanceof TextView) {
            TextView vText = (TextView) v;
            description.append(vText.getText());
            description.append(","); // Allow Talkback to pause between sections.
        }
    }

    private boolean isExtStorageEncrypted() {
        String state = VoldProperties.decrypt().orElse("");
        return !"".equals(state);
    }

    private void loadAccountList(final UserManager um) {
        View accountsLabel = mContentView.findViewById(R.id.accounts_label);
        LinearLayout contents = (LinearLayout) mContentView.findViewById(R.id.accounts);
        contents.removeAllViews();

        Context context = getActivity();
        final List<UserInfo> profiles = um.getProfiles(UserHandle.myUserId());
        final int profilesSize = profiles.size();

        AccountManager mgr = AccountManager.get(context);

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);

        int accountsCount = 0;
        for (int profileIndex = 0; profileIndex < profilesSize; profileIndex++) {
            final UserInfo userInfo = profiles.get(profileIndex);
            final int profileId = userInfo.id;
            final UserHandle userHandle = new UserHandle(profileId);
            Account[] accounts = mgr.getAccountsAsUser(profileId);
            final int N = accounts.length;
            if (N == 0) {
                continue;
            }
            accountsCount += N;

            AuthenticatorDescription[] descs = AccountManager.get(context)
                    .getAuthenticatorTypesAsUser(profileId);
            final int M = descs.length;

            if (profilesSize > 1) {
                View titleView = Utils.inflateCategoryHeader(inflater, contents);
                final TextView titleText = (TextView) titleView.findViewById(android.R.id.title);
                titleText.setText(userInfo.isManagedProfile() ? R.string.category_work
                        : R.string.category_personal);
                contents.addView(titleView);
            }

            for (int i = 0; i < N; i++) {
                Account account = accounts[i];
                AuthenticatorDescription desc = null;
                for (int j = 0; j < M; j++) {
                    if (account.type.equals(descs[j].type)) {
                        desc = descs[j];
                        break;
                    }
                }
                if (desc == null) {
                    Log.w(TAG, "No descriptor for account name=" + account.name
                            + " type=" + account.type);
                    continue;
                }
                Drawable icon = null;
                try {
                    if (desc.iconId != 0) {
                        Context authContext = context.createPackageContextAsUser(desc.packageName,
                                0, userHandle);
                        icon = context.getPackageManager().getUserBadgedIcon(
                                authContext.getDrawable(desc.iconId), userHandle);
                    }
                } catch (PackageManager.NameNotFoundException e) {
                    Log.w(TAG, "Bad package name for account type " + desc.type);
                } catch (Resources.NotFoundException e) {
                    Log.w(TAG, "Invalid icon id for account type " + desc.type, e);
                }
                if (icon == null) {
                    icon = context.getPackageManager().getDefaultActivityIcon();
                }

                View child = inflater.inflate(R.layout.master_clear_account, contents, false);
                ((ImageView) child.findViewById(android.R.id.icon)).setImageDrawable(icon);
                ((TextView) child.findViewById(android.R.id.title)).setText(account.name);
                contents.addView(child);
            }
        }

        if (accountsCount > 0) {
            accountsLabel.setVisibility(View.VISIBLE);
            contents.setVisibility(View.VISIBLE);
        }
        // Checking for all other users and their profiles if any.
        View otherUsers = mContentView.findViewById(R.id.other_users_present);
        final boolean hasOtherUsers = (um.getUserCount() - profilesSize) > 0;
        otherUsers.setVisibility(hasOtherUsers ? View.VISIBLE : View.GONE);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        final Context context = getContext();
        final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(context,
                UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId());
        final UserManager um = UserManager.get(context);
        final boolean disallow = !um.isAdminUser() || RestrictedLockUtilsInternal
                .hasBaseUserRestriction(context, UserManager.DISALLOW_FACTORY_RESET,
                        UserHandle.myUserId());
        if (disallow && !Utils.isDemoUser(context)) {
            return inflater.inflate(R.layout.master_clear_disallowed_screen, null);
        } else if (admin != null) {
            new ActionDisabledByAdminDialogHelper(getActivity())
                    .prepareDialogBuilder(UserManager.DISALLOW_FACTORY_RESET, admin)
                    .setOnDismissListener(__ -> getActivity().finish())
                    .show();
            return new View(getContext());
        }

        mContentView = inflater.inflate(R.layout.master_clear, null);

        establishInitialState();
        return mContentView;
    }

    @Override
    public int getMetricsCategory() {
        return SettingsEnums.MASTER_CLEAR;
    }
}
