/*
 * Copyright (C) 2020 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.car.provision;

import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_FIRST_USER;
import static android.app.Activity.RESULT_OK;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TRIGGER;
import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_QR_CODE;
import static android.car.settings.CarSettings.Secure.KEY_ENABLE_INITIAL_NOTICE_SCREEN_TO_USER;
import static android.car.settings.CarSettings.Secure.KEY_SETUP_WIZARD_IN_PROGRESS;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;

import com.android.car.setupwizardlib.util.CarDrivingStateMonitor;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * Reference implementeation for a Car SetupWizard.
 *
 * <p>Features:
 *
 * <ul>
 *   <li>Shows UI where user can confirm setup.
 *   <li>Listen to UX restriction events, so it exits setup when the car moves.
 *   <li>Add option to setup managed-provisioning mode.
 *   <li>Sets car-specific properties.
 * </ul>
 *
 * <p>By default, it doesn't show the UI, unless the {@code persist.dev.car_provision.show_ui}
 * property is set to {@code true}. For example, you can change it by running something like:
 <pre><code>
     adb root
     adb shell setprop persist.dev.car_provision.show_ui true && \
     adb shell pm enable --user cur com.android.car.provision/.DefaultActivity &&\
     adb shell settings put secure --user cur user_setup_complete 0 && \
     adb shell settings put secure --user 0 user_setup_complete 0 &&\
     adb shell settings put global device_provisioned 0 &&\
     adb shell rm -f /data/system/device_policies_version &&\
     adb shell rm -f /data/system/device_policies.xml &&\
     adb shell rm -f /data/system/device_owner_2.xml ;\
     adb shell rm -f /data/system/users/`adb shell am get-current-user`/profile_owner.xml
     adb shell stop && adb shell start
  <code></pre>
 */
public final class DefaultActivity extends Activity {

    static final String TAG = "CarProvision";

    // TODO(b/170333009): copied from ManagedProvisioning app, as they're hidden;
    private static final String PROVISION_FINALIZATION_INSIDE_SUW =
            "android.app.action.PROVISION_FINALIZATION_INSIDE_SUW";
    private static final int RESULT_CODE_PROFILE_OWNER_SET = 122;
    private static final int RESULT_CODE_DEVICE_OWNER_SET = 123;


    private static final int REQUEST_CODE_STEP1 = 42;
    private static final int REQUEST_CODE_STEP2_PO = 43;
    private static final int REQUEST_CODE_STEP2_DO = 44;

    private static final int NOTIFICATION_ID = 108;
    private static final String IMPORTANCE_DEFAULT_ID = "importance_default";

    private static final List<DpcInfo> sSupportedDpcApps = new ArrayList<>(2);

    private static final String TEST_DPC_NAME = "TestDPC (downloadable)";
    private static final String TEST_DPC_PACKAGE = "com.afwsamples.testdpc";
    private static final String TEST_DPC_LEGACY_ACTIVITY = TEST_DPC_PACKAGE
            + ".SetupManagementLaunchActivity";
    private static final String TEST_DPC_RECEIVER = TEST_DPC_PACKAGE
            + ".DeviceAdminReceiver";
    private static final String LOCAL_TEST_DPC_NAME = "TestDPC (local only)";

    private static final String SHOW_UI_SYSTEM_PROPERTY = "persist.dev.car_provision.show_ui";

    static {
        DpcInfo testDpc = new DpcInfo(TEST_DPC_NAME,
                TEST_DPC_PACKAGE,
                TEST_DPC_LEGACY_ACTIVITY,
                TEST_DPC_RECEIVER,
                "gJD2YwtOiWJHkSMkkIfLRlj-quNqG1fb6v100QmzM9w=",
                "https://testdpc-latest-apk.appspot.com/preview");
        // Locally-built version of the TestDPC
        DpcInfo localTestDpc = new DpcInfo(LOCAL_TEST_DPC_NAME,
                TEST_DPC_PACKAGE,
                TEST_DPC_LEGACY_ACTIVITY,
                TEST_DPC_RECEIVER,
                /* checkSum= */ null,
                /* downloadUrl = */ null);
        sSupportedDpcApps.add(testDpc);
        sSupportedDpcApps.add(localTestDpc);
    }

    private CarDrivingStateMonitor mCarDrivingStateMonitor;

    private TextView mErrorsTextView;
    private Button mFinishSetupButton;
    private Button mFactoryResetButton;
    private Spinner mDpcAppsSpinner;
    private Button mLegacyProvisioningWorkflowButton;
    private Button mProvisioningWorkflowButton;

    private final BroadcastReceiver mDrivingStateExitReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "onReceive(): " + intent);
            exitSetup();
        }
    };

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

        int userId = getUserId();
        Log.i(TAG, "onCreate() for user " + userId + " Intent: " + getIntent());

        if (userId == UserHandle.USER_SYSTEM && UserManager.isHeadlessSystemUserMode()) {
            // System user will be provisioned together with the first non-system user
            Log.i(TAG, "onCreate(): skipping setup on headless system user");
            disableSelfAndFinish();
            return;
        }

        if (!showUi()) {
            Log.w(TAG, "onCreate(): skipping UI because " + SHOW_UI_SYSTEM_PROPERTY
                    + " was not set to true");
            finishSetup();
            return;
        }

        DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class);
        if (dpm.isDeviceManaged()) {
            Log.i(TAG, "onCreate(): skipping UI on managed device");
            finishSetup();
            return;
        }

        setCarSetupInProgress(true);
        setContentView(R.layout.default_activity);

        mErrorsTextView = findViewById(R.id.error_message);
        mFinishSetupButton = findViewById(R.id.finish_setup);
        mFactoryResetButton = findViewById(R.id.factory_reset);
        mDpcAppsSpinner = findViewById(R.id.dpc_apps);
        mLegacyProvisioningWorkflowButton = findViewById(R.id.legacy_provision_workflow);
        mProvisioningWorkflowButton = findViewById(R.id.provision_workflow);

        mLegacyProvisioningWorkflowButton
                .setOnClickListener((v) -> launchLegacyProvisioningWorkflow());
        mProvisioningWorkflowButton.setOnClickListener((v) -> launchProvisioningWorkflow());
        mFinishSetupButton.setOnClickListener((v) -> finishSetup());
        mFactoryResetButton.setOnClickListener((v) -> factoryReset());

        updateUi();
        setManagedProvisioning(dpm);
        startMonitor();
    }

    private boolean showUi() {
        boolean result = false;
        try {
            result = SystemProperties.getBoolean(SHOW_UI_SYSTEM_PROPERTY, false);
        } catch (Exception e) {
            Log.w(TAG, "error getting property " + SHOW_UI_SYSTEM_PROPERTY);
        }
        return result;
    }

    private void startMonitor() {
        Log.d(TAG, "startMonitor()");
        registerReceiver(mDrivingStateExitReceiver,
                new IntentFilter(CarDrivingStateMonitor.EXIT_BROADCAST_ACTION));

        mCarDrivingStateMonitor = CarDrivingStateMonitor.get(this);
        mCarDrivingStateMonitor.startMonitor();
    }

    @Override
    public void finish() {
        Log.i(TAG, "finish() for user " + getUserId());

        stopMonitor();

        super.finish();
    };

    @Override
    public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
        if (args == null || args.length == 0) {
            showDpcs(pw);
            showHelp(pw);
            return;
        }

        if (args[0].equals("--help")) {
            showHelp(pw);
            return;
        }

        addDpc(pw, args);
    };

    private void showDpcs(PrintWriter pw) {
        pw.printf("%d DPCs\n", sSupportedDpcApps.size());
        sSupportedDpcApps.forEach((dpc) -> pw.printf("\t%s\n", dpc));
    }

    private void showHelp(PrintWriter pw) {
        pw.println("\nTo add a new DPC, use: --name name --package-name package-name"
                + "--receiver-name receiver-name [--legacy-activity-name legacy-activity-name] "
                + "[--checksum checksum] [--download-url download-url]");
    }

    private void addDpc(PrintWriter pw, String[] args) {
        String name = null;
        String packageName = null;
        String legacyActivityName = null;
        String receiverName = null;
        String checkSum = null;
        String downloadUrl = null;

        for (int i = 0; i < args.length; i++) {
            try {
                switch (args[i]) {
                    case "--name":
                        name = args[++i];
                        break;
                    case "--package-name":
                        packageName = args[++i];
                        break;
                    case "--legacy-activity-name":
                        legacyActivityName = args[++i];
                        break;
                    case "--receiver-name":
                        receiverName = args[++i];
                        break;
                    case "--checksum":
                        checkSum = args[++i];
                        break;
                    case "--download-url":
                        downloadUrl = args[++i];
                        break;
                    default:
                        pw.printf("Invalid option at index %d: %s\n", i, args[i]);
                        return;
                }
            } catch (Exception e) {
                // most likely a missing arg...
                pw.printf("Error handing arg %d: %s\n", i, e);
                return;
            }
        }

        DpcInfo dpc = new DpcInfo(name, packageName, legacyActivityName, receiverName, checkSum,
                downloadUrl);
        Log.i(TAG, "Adding new DPC from dump(): " + dpc);
        sSupportedDpcApps.add(dpc);
        pw.printf("Added new DPC: %s\n", dpc);

        updateUi();
    }

    private void stopMonitor() {
        Log.d(TAG, "stopMonitor()");

        if (mCarDrivingStateMonitor == null) {
            // Happens when device is managed (and startMonitor() is skipped)
            Log.d(TAG, "Already stopped (or never stopped)");
            return;
        }

        if (mDrivingStateExitReceiver != null) {
            unregisterReceiver(mDrivingStateExitReceiver);
        }

        mCarDrivingStateMonitor.stopMonitor();
        mCarDrivingStateMonitor = null;
    }

    private void updateUi() {
        String[] appNames = new String[sSupportedDpcApps.size()];
        for (int i = 0; i < sSupportedDpcApps.size(); i++) {
            appNames[i] = sSupportedDpcApps.get(i).name;
        }
        mDpcAppsSpinner.setAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_spinner_item, appNames));
        mDpcAppsSpinner.setSelection(appNames.length - 1);
    }

    private void setManagedProvisioning(DevicePolicyManager dpm) {
        if (!getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) {
            Log.i(TAG, "Disabling provisioning buttons because device does not have the "
                    + PackageManager.FEATURE_DEVICE_ADMIN + " feature");
            return;
        }
        if (!dpm.isProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE)) {
            Log.w(TAG, "Disabling provisioning buttons because device cannot be provisioned - "
                    + "it can only be set on first boot");
            return;
        }

        mProvisioningWorkflowButton.setEnabled(true);
        mLegacyProvisioningWorkflowButton.setEnabled(true);
    }

    private boolean checkDpcAppExists(String dpcApp) {
        if (!checkAppExists(dpcApp, UserHandle.USER_SYSTEM)) return false;
        if (!checkAppExists(dpcApp, getUserId())) return false;
        return true;
    }

    private boolean checkAppExists(String app, int userId) {
        Log.d(TAG, "Checking if " + app + " exits for user " + userId);
        try {
            PackageInfo info = getPackageManager().getPackageInfoAsUser(app, /* flags= */ 0,
                    userId);
            if (info == null) {
                Log.i(TAG, "No app " + app + " for user " + userId);
                return false;
            }
            Log.d(TAG, "Found it: " + info);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        } catch (Exception e) {
            Log.e(TAG, "Error checking if " + app + " exists for user " + userId, e);
            return false;
        }
    }

    private void finishSetup() {
        Log.i(TAG, "finishing setup for user " + getUserId());
        provisionUserAndDevice();
        disableSelfAndFinish();
    }

    private void factoryReset() {
        new AlertDialog.Builder(this).setMessage(R.string.factory_reset_warning)
            .setPositiveButton(android.R.string.ok, (d, w)->sendFactoryResetIntent())
            .show();
    }

    private void sendFactoryResetIntent() {
        provisionUserAndDevice();

        Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
        intent.setPackage("android");
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        intent.putExtra(Intent.EXTRA_REASON, "Requested by user on SUW");

        Log.i(TAG, "factory resetting device with intent " + intent);
        sendBroadcast(intent);

        disableSelfAndFinish();
    }

    private void provisionUserAndDevice() {
        Log.d(TAG, "setting Settings properties");
        // Add a persistent setting to allow other apps to know the device has been provisioned.
        if (!isDeviceProvisioned()) {
            Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
        }

        maybeMarkSystemUserSetupComplete();
        Log.v(TAG, "Marking USER_SETUP_COMPLETE for user " + getUserId());
        markUserSetupComplete(this);

        // Set car-specific properties
        setCarSetupInProgress(false);
        Settings.Secure.putInt(getContentResolver(), KEY_ENABLE_INITIAL_NOTICE_SCREEN_TO_USER, 0);
    }

    private boolean isDeviceProvisioned() {
        try {
            return Settings.Global.getInt(getContentResolver(),
                    Settings.Global.DEVICE_PROVISIONED) == 1;
        } catch (SettingNotFoundException e) {
            Log.wtf(TAG, "DEVICE_PROVISIONED is not found.");
            return false;
        }
    }

    private boolean isUserSetupComplete(Context context) {
        return Settings.Secure.getInt(context.getContentResolver(),
                Settings.Secure.USER_SETUP_COMPLETE, /* default= */ 0) == 1;
    }

    private void maybeMarkSystemUserSetupComplete() {
        Context systemUserContext = getApplicationContext().createContextAsUser(
                UserHandle.SYSTEM, /* flags= */ 0);
        if (!isUserSetupComplete(systemUserContext) && getUserId() != UserHandle.USER_SYSTEM
                && UserManager.isHeadlessSystemUserMode()) {
            Log.v(TAG, "Marking USER_SETUP_COMPLETE for system user");
            markUserSetupComplete(systemUserContext);
        }
    }

    private void setCarSetupInProgress(boolean inProgress) {
        Settings.Secure.putInt(getContentResolver(), KEY_SETUP_WIZARD_IN_PROGRESS,
                inProgress ? 1 : 0);
    }

    private void markUserSetupComplete(Context context) {
        Settings.Secure.putInt(context.getContentResolver(),
                Settings.Secure.USER_SETUP_COMPLETE, 1);
    }

    private void exitSetup() {
        Log.d(TAG, "exiting setup early for user " + getUserId());
        provisionUserAndDevice();
        notifySetupExited();
        disableSelfAndFinish();
    }

    private void notifySetupExited() {
        Log.d(TAG, "Sending exited setup notification");

        NotificationManager notificationMgr = getSystemService(NotificationManager.class);
        notificationMgr.createNotificationChannel(new NotificationChannel(
                IMPORTANCE_DEFAULT_ID, "Importance Default",
                NotificationManager.IMPORTANCE_DEFAULT));
        Notification notification = new Notification
                .Builder(this, IMPORTANCE_DEFAULT_ID)
                .setContentTitle(getString(R.string.exited_setup_title))
                .setContentText(getString(R.string.exited_setup_content))
                .setCategory(Notification.CATEGORY_CAR_INFORMATION)
                .setSmallIcon(R.drawable.car_ic_mode)
                .build();
        notificationMgr.notify(NOTIFICATION_ID, notification);
    }

    private DpcInfo getSelectedDpcInfo() {
        return sSupportedDpcApps.get(mDpcAppsSpinner.getSelectedItemPosition());
    }

    private void launchLegacyProvisioningWorkflow() {
        DpcInfo dpcInfo = getSelectedDpcInfo();
        if (!checkDpcAppExists(dpcInfo.packageName)) {
            showErrorMessage("Cannot provision device because " + dpcInfo.packageName
                    + " is not available.\n Make sure it's installed for both user 0 and user "
                    + getUserId());
            return;
        }

        Intent intent = new Intent();
        intent.setComponent(dpcInfo.getLegacyActivityComponentName());
        Log.i(TAG, "Provisioning device using LEGACY workflow while running as user "
                + getUserId() + ". DPC: " + dpcInfo + ". Intent: " + intent);
        startActivityForResult(intent, REQUEST_CODE_STEP1);
    }

    private void launchProvisioningWorkflow() {
        DpcInfo dpcInfo = getSelectedDpcInfo();

        Intent intent = new Intent(ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE);
        // TODO(b/170333009): add a UI with options for EXTRA_PROVISIONING_TRIGGER.
        intent.putExtra(EXTRA_PROVISIONING_TRIGGER, PROVISIONING_TRIGGER_QR_CODE);
        intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
                dpcInfo.getAdminReceiverComponentName());
        if (dpcInfo.checkSum != null) {
            intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM, dpcInfo.checkSum);
        }
        if (dpcInfo.downloadUrl != null) {
            intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION,
                    dpcInfo.downloadUrl);
        }

        Log.i(TAG, "Provisioning device using NEW workflow while running as user "
                + getUserId() + ". DPC: " + dpcInfo + ". Intent: " + intent);

        startActivityForResult(intent, REQUEST_CODE_STEP1);
    }

    private void disableSelfAndFinish() {
        Log.d(TAG, "disableSelfAndFinish()");

        // Remove this activity from the package manager.
        PackageManager pm = getPackageManager();
        ComponentName name = new ComponentName(this, DefaultActivity.class);
        Log.i(TAG, "Disabling itself (" + name + ") for user " + getUserId());
        pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);

        finish();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.d(TAG, "onActivityResult(): request=" + requestCode + ", result="
                + resultCodeToString(resultCode) + ", data=" + data);

        switch (requestCode) {
            case REQUEST_CODE_STEP1:
                onProvisioningStep1Result(resultCode);
                break;
            case REQUEST_CODE_STEP2_PO:
            case REQUEST_CODE_STEP2_DO:
                onProvisioningStep2Result(requestCode, resultCode);
                break;
            default:
                showErrorMessage("onActivityResult(): invalid request code " + requestCode);

        }
    }

    private void onProvisioningStep1Result(int resultCode) {
        int requestCodeStep2;
        switch (resultCode) {
            case RESULT_CODE_PROFILE_OWNER_SET:
                requestCodeStep2 = REQUEST_CODE_STEP2_PO;
                break;
            case RESULT_CODE_DEVICE_OWNER_SET:
                requestCodeStep2 = REQUEST_CODE_STEP2_DO;
                break;
            default:
                showErrorMessage("onProvisioningStep1Result(): invalid result code "
                        + resultCodeToString(resultCode)
                        + getManagedProvisioningFailureWarning());
                return;
        }
        Intent intent = new Intent(PROVISION_FINALIZATION_INSIDE_SUW)
                .addCategory(Intent.CATEGORY_DEFAULT);
        Log.i(TAG, "Finalizing DPC with " + intent);
        startActivityForResult(intent, requestCodeStep2);
    }

    private String getManagedProvisioningFailureWarning() {
        return "\n\n" + getString(R.string.provision_failure_message);
    }

    private void onProvisioningStep2Result(int requestCode, int resultCode) {
        boolean doMode = requestCode == REQUEST_CODE_STEP2_DO;
        if (resultCode != RESULT_OK) {
            StringBuilder message = new StringBuilder("onProvisioningStep2Result(): "
                    + "invalid result code ").append(resultCode);
            if (doMode) {
                message.append(getManagedProvisioningFailureWarning());
            }
            showErrorMessage(message.toString());
            return;
        }

        Log.i(TAG, (doMode ? "Device owner" : "Profile owner") + " mode provisioned!");
        finishSetup();
    }

    private static String resultCodeToString(int resultCode)  {
        StringBuilder result = new StringBuilder();
        switch (resultCode) {
            case RESULT_OK:
                result.append("RESULT_OK");
                break;
            case RESULT_CANCELED:
                result.append("RESULT_CANCELED");
                break;
            case RESULT_FIRST_USER:
                result.append("RESULT_FIRST_USER");
                break;
            case RESULT_CODE_PROFILE_OWNER_SET:
                result.append("RESULT_CODE_PROFILE_OWNER_SET");
                break;
            case RESULT_CODE_DEVICE_OWNER_SET:
                result.append("RESULT_CODE_DEVICE_OWNER_SET");
                break;
            default:
                result.append("UNKNOWN_CODE");
        }
        return result.append('(').append(resultCode).append(')').toString();
    }

    private void showErrorMessage(String message) {
        Log.e(TAG, "Error: " + message);
        mErrorsTextView.setText(message);
        findViewById(R.id.errors_container).setVisibility(View.VISIBLE);
    }
}
