/*
 * Copyright (C) 2024 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.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import androidx.core.app.NotificationCompat;

import com.android.settings.R;
import com.android.settings.flags.Flags;
import com.android.settingslib.bluetooth.BluetoothUtils;

/**
 * BluetoothKeyMissingReceiver is a receiver for Bluetooth key missing error when reconnecting to a
 * bonded bluetooth device.
 */
public final class BluetoothKeyMissingReceiver extends BroadcastReceiver {
    private static final String TAG = "BtKeyMissingReceiver";
    private static final String CHANNEL_ID = "bluetooth_notification_channel";
    private static final int NOTIFICATION_ID = android.R.drawable.stat_sys_data_bluetooth;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (!Flags.enableBluetoothKeyMissingDialog()) {
            return;
        }
        String action = intent.getAction();
        if (action == null) {
            return;
        }

        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        if (device == null) {
            return;
        }
        if (BluetoothUtils.isExclusivelyManagedBluetoothDevice(context, device)) {
            Log.d(TAG, "Exclusively managed device " + device + ", skip");
            return;
        }
        PowerManager powerManager = context.getSystemService(PowerManager.class);
        if (TextUtils.equals(action, BluetoothDevice.ACTION_KEY_MISSING)) {
            Log.d(TAG, "Receive ACTION_KEY_MISSING");
            if (device.getBondState() == BluetoothDevice.BOND_NONE) {
                Log.d(
                        TAG,
                        "Device " + device.getAnonymizedAddress() + " is already unbonded, skip.");
                return;
            }
            Integer keyMissingCount = BluetoothUtils.getKeyMissingCount(device);
            boolean keyMissingFirstTime = keyMissingCount == null || keyMissingCount == 1;
            if (shouldShowDialog(context, device, powerManager)) {
                if (keyMissingFirstTime) {
                    Intent pairingIntent = getKeyMissingDialogIntent(context, device);
                    Log.d(TAG, "Show key missing dialog:" + device);
                    context.startActivityAsUser(pairingIntent, UserHandle.CURRENT);
                } else {
                    Log.d(TAG, "Show key missing toast:" + device);
                    Toast.makeText(
                                    context,
                                    context.getString(
                                            R.string.bluetooth_key_missing_toast,
                                            device.getAlias()),
                                    Toast.LENGTH_SHORT)
                            .show();
                }
            } else if (keyMissingFirstTime) {
                Log.d(TAG, "Show key missing notification: " + device);
                showNotification(context, device);
            }
        }
    }

    private Intent getKeyMissingDialogIntent(Context context, BluetoothDevice device) {
        Intent pairingIntent = new Intent();
        pairingIntent.setClass(context, BluetoothKeyMissingDialog.class);
        pairingIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        pairingIntent.setAction(BluetoothDevice.ACTION_KEY_MISSING);
        pairingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        return pairingIntent;
    }

    private boolean shouldShowDialog(
            Context context, BluetoothDevice device, PowerManager powerManager) {
        return LocalBluetoothPreferences.shouldShowDialogInForeground(context, device)
                && powerManager.isInteractive();
    }

    private void showNotification(Context context, BluetoothDevice bluetoothDevice) {
        NotificationManager nm = context.getSystemService(NotificationManager.class);
        NotificationChannel notificationChannel =
                new NotificationChannel(
                        CHANNEL_ID,
                        context.getString(R.string.bluetooth),
                        NotificationManager.IMPORTANCE_HIGH);
        nm.createNotificationChannel(notificationChannel);

        PendingIntent pairIntent =
                PendingIntent.getActivity(
                        context,
                        0,
                        getKeyMissingDialogIntent(context, bluetoothDevice),
                        PendingIntent.FLAG_ONE_SHOT
                                | PendingIntent.FLAG_UPDATE_CURRENT
                                | PendingIntent.FLAG_IMMUTABLE);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(context,
                CHANNEL_ID)
                .setSmallIcon(android.R.drawable.stat_sys_data_bluetooth)
                .setTicker(context.getString(R.string.bluetooth_notif_ticker))
                .setLocalOnly(true);
        builder.setContentTitle(
                        context.getString(
                                R.string.bluetooth_key_missing_title, bluetoothDevice.getAlias()))
                .setContentText(context.getString(R.string.bluetooth_key_missing_message))
                .setContentIntent(pairIntent)
                .setAutoCancel(true)
                .setDefaults(Notification.DEFAULT_SOUND)
                .setColor(
                        context.getColor(
                                com.android.internal.R.color.system_notification_accent_color));

        nm.notify(NOTIFICATION_ID, builder.build());
    }
}
