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

import android.annotation.NonNull;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

import androidx.appcompat.app.AlertDialog;

import com.android.settings.R;
import com.android.settingslib.bluetooth.BluetoothDiscoverableTimeoutReceiver;

/**
 * RequestPermissionActivity asks the user whether to enable discovery. This is
 * usually started by an application wanted to start bluetooth and or discovery
 */
public class RequestPermissionActivity extends Activity implements
        DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
    // Command line to test this
    // adb shell am start -a android.bluetooth.adapter.action.REQUEST_ENABLE
    // adb shell am start -a android.bluetooth.adapter.action.REQUEST_DISCOVERABLE
    // adb shell am start -a android.bluetooth.adapter.action.REQUEST_DISABLE

    private static final String TAG = "BtRequestPermission";

    private static final int MAX_DISCOVERABLE_TIMEOUT = 3600; // 1 hr

    static final int REQUEST_ENABLE = 1;
    static final int REQUEST_ENABLE_DISCOVERABLE = 2;
    static final int REQUEST_DISABLE = 3;

    private BluetoothAdapter mBluetoothAdapter;

    private int mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT;

    private int mRequest;

    private AlertDialog mDialog;

    private BroadcastReceiver mReceiver;

    private @NonNull CharSequence mAppLabel;

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

        setResult(Activity.RESULT_CANCELED);

        // Note: initializes mBluetoothAdapter and returns true on error
        if (parseIntent()) {
            finish();
            return;
        }

        int btState = mBluetoothAdapter.getState();

        if (mRequest == REQUEST_DISABLE) {
            switch (btState) {
                case BluetoothAdapter.STATE_OFF:
                case BluetoothAdapter.STATE_TURNING_OFF: {
                    proceedAndFinish();
                } break;

                case BluetoothAdapter.STATE_ON:
                case BluetoothAdapter.STATE_TURNING_ON: {
                    Intent intent = new Intent(this, RequestPermissionHelperActivity.class);
                    intent.putExtra(RequestPermissionHelperActivity.EXTRA_APP_LABEL, mAppLabel);
                    intent.setAction(RequestPermissionHelperActivity
                                .ACTION_INTERNAL_REQUEST_BT_OFF);

                    startActivityForResult(intent, 0);
                } break;

                default: {
                    Log.e(TAG, "Unknown adapter state: " + btState);
                    cancelAndFinish();
                } break;
            }
        } else {
            switch (btState) {
                case BluetoothAdapter.STATE_OFF:
                case BluetoothAdapter.STATE_TURNING_OFF:
                case BluetoothAdapter.STATE_TURNING_ON: {
                    /*
                     * Strictly speaking STATE_TURNING_ON belong with STATE_ON;
                     * however, BT may not be ready when the user clicks yes and we
                     * would fail to turn on discovery mode. By kicking this to the
                     * RequestPermissionHelperActivity, this class will handle that
                     * case via the broadcast receiver.
                     */

                    /*
                     * Start the helper activity to:
                     * 1) ask the user about enabling bt AND discovery
                     * 2) enable BT upon confirmation
                     */
                    Intent intent = new Intent(this, RequestPermissionHelperActivity.class);
                    intent.setAction(RequestPermissionHelperActivity.ACTION_INTERNAL_REQUEST_BT_ON);
                    intent.putExtra(RequestPermissionHelperActivity.EXTRA_APP_LABEL, mAppLabel);
                    if (mRequest == REQUEST_ENABLE_DISCOVERABLE) {
                        intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, mTimeout);
                    }
                    startActivityForResult(intent, 0);
                } break;

                case BluetoothAdapter.STATE_ON: {
                    if (mRequest == REQUEST_ENABLE) {
                        // Nothing to do. Already enabled.
                        proceedAndFinish();
                    } else {
                        // Ask the user about enabling discovery mode
                        createDialog();
                    }
                } break;

                default: {
                    Log.e(TAG, "Unknown adapter state: " + btState);
                    cancelAndFinish();
                } break;
            }
        }
    }

    private void createDialog() {
        if (getResources().getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog)) {
            onClick(null, DialogInterface.BUTTON_POSITIVE);
            return;
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        // Non-null receiver means we are toggling
        if (mReceiver != null) {
            switch (mRequest) {
                case REQUEST_ENABLE:
                case REQUEST_ENABLE_DISCOVERABLE: {
                    builder.setMessage(getString(R.string.bluetooth_turning_on));
                } break;

                default: {
                    builder.setMessage(getString(R.string.bluetooth_turning_off));
                } break;
            }
            builder.setCancelable(false);
        } else {
            // Ask the user whether to turn on discovery mode or not
            // For lasting discoverable mode there is a different message
            if (mTimeout == BluetoothDiscoverableEnabler.DISCOVERABLE_TIMEOUT_NEVER) {
                CharSequence message = mAppLabel != null
                        ? getString(R.string.bluetooth_ask_lasting_discovery, mAppLabel)
                        : getString(R.string.bluetooth_ask_lasting_discovery_no_name);
                builder.setMessage(message);
            } else {
                CharSequence message = mAppLabel != null
                        ? getString(R.string.bluetooth_ask_discovery, mAppLabel, mTimeout)
                        : getString(R.string.bluetooth_ask_discovery_no_name, mTimeout);
                builder.setMessage(message);
            }
            builder.setPositiveButton(getString(R.string.allow), this);
            builder.setNegativeButton(getString(R.string.deny), this);
        }

        builder.setOnDismissListener(this);
        mDialog = builder.create();
        mDialog.show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != Activity.RESULT_OK) {
            cancelAndFinish();
            return;
        }

        switch (mRequest) {
            case REQUEST_ENABLE:
            case REQUEST_ENABLE_DISCOVERABLE: {
                if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
                    proceedAndFinish();
                } else {
                    // If BT is not up yet, show "Turning on Bluetooth..."
                    mReceiver = new StateChangeReceiver();
                    registerReceiver(mReceiver, new IntentFilter(
                            BluetoothAdapter.ACTION_STATE_CHANGED));
                    createDialog();
                }
            } break;

            case REQUEST_DISABLE: {
                if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
                    proceedAndFinish();
                } else {
                    // If BT is not up yet, show "Turning off Bluetooth..."
                    mReceiver = new StateChangeReceiver();
                    registerReceiver(mReceiver, new IntentFilter(
                            BluetoothAdapter.ACTION_STATE_CHANGED));
                    createDialog();
                }
            } break;

            default: {
                cancelAndFinish();
            } break;
        }
    }

    public void onClick(DialogInterface dialog, int which) {
        switch (which) {
            case DialogInterface.BUTTON_POSITIVE:
                proceedAndFinish();
                break;

            case DialogInterface.BUTTON_NEGATIVE:
                cancelAndFinish();
                break;
        }
    }

    @Override
    public void onDismiss(final DialogInterface dialog) {
        cancelAndFinish();
    }

    private void proceedAndFinish() {
        int returnCode;

        if (mRequest == REQUEST_ENABLE || mRequest == REQUEST_DISABLE) {
            // BT toggled. Done
            returnCode = RESULT_OK;
        } else if (mBluetoothAdapter.setScanMode(
                BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, mTimeout)) {
            // If already in discoverable mode, this will extend the timeout.
            long endTime = System.currentTimeMillis() + (long) mTimeout * 1000;
            LocalBluetoothPreferences.persistDiscoverableEndTimestamp(
                    this, endTime);
            if (0 < mTimeout) {
               BluetoothDiscoverableTimeoutReceiver.setDiscoverableAlarm(this, endTime);
            }
            returnCode = mTimeout;
            // Activity.RESULT_FIRST_USER should be 1
            if (returnCode < RESULT_FIRST_USER) {
                returnCode = RESULT_FIRST_USER;
            }
        } else {
            returnCode = RESULT_CANCELED;
        }

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

        setResult(returnCode);
        finish();
    }

    private void cancelAndFinish() {
        setResult(Activity.RESULT_CANCELED);
        finish();
    }

    /**
     * Parse the received Intent and initialize mBluetoothAdapter.
     * @return true if an error occurred; false otherwise
     */
    private boolean parseIntent() {
        Intent intent = getIntent();
        if (intent == null) {
            return true;
        }
        if (intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
            mRequest = REQUEST_ENABLE;
        } else if (intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
            mRequest = REQUEST_DISABLE;
        } else if (intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)) {
            mRequest = REQUEST_ENABLE_DISCOVERABLE;
            mTimeout = intent.getIntExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
                    BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT);

            Log.d(TAG, "Setting Bluetooth Discoverable Timeout = " + mTimeout);

            if (mTimeout < 1 || mTimeout > MAX_DISCOVERABLE_TIMEOUT) {
                mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT;
            }
        } else {
            Log.e(TAG, "Error: this activity may be started only with intent "
                    + BluetoothAdapter.ACTION_REQUEST_ENABLE + " or "
                    + BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            setResult(RESULT_CANCELED);
            return true;
        }

        String packageName = getCallingPackage();
        if (TextUtils.isEmpty(packageName)) {
            packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
        }
        if (!TextUtils.isEmpty(packageName)) {
            try {
                ApplicationInfo applicationInfo = getPackageManager().getApplicationInfo(
                        packageName, 0);
                mAppLabel = applicationInfo.loadSafeLabel(getPackageManager(),
                        PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX,
                        PackageItemInfo.SAFE_LABEL_FLAG_TRIM
                                | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
            } catch (PackageManager.NameNotFoundException e) {
                Log.e(TAG, "Couldn't find app with package name " + packageName);
                setResult(RESULT_CANCELED);
                return true;
            }
        }

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            Log.e(TAG, "Error: there's a problem starting Bluetooth");
            setResult(RESULT_CANCELED);
            return true;
        }

        return false;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
            mReceiver = null;
        }
    }

    @Override
    public void onBackPressed() {
        setResult(RESULT_CANCELED);
        super.onBackPressed();
    }

    private final class StateChangeReceiver extends BroadcastReceiver {
        private static final long TOGGLE_TIMEOUT_MILLIS = 10000; // 10 sec

        public StateChangeReceiver() {
            getWindow().getDecorView().postDelayed(() -> {
                if (!isFinishing() && !isDestroyed()) {
                    cancelAndFinish();
                }
            }, TOGGLE_TIMEOUT_MILLIS);
        }

        public void onReceive(Context context, Intent intent) {
            if (intent == null) {
                return;
            }
            final int currentState = intent.getIntExtra(
                    BluetoothAdapter.EXTRA_STATE, BluetoothDevice.ERROR);
            switch (mRequest) {
                case REQUEST_ENABLE:
                case REQUEST_ENABLE_DISCOVERABLE: {
                    if (currentState == BluetoothAdapter.STATE_ON) {
                        proceedAndFinish();
                    }
                } break;

                case REQUEST_DISABLE: {
                    if (currentState == BluetoothAdapter.STATE_OFF) {
                        proceedAndFinish();
                    }
                } break;
            }
        }
    }
}
