package com.android.car.messenger;


import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothMapClient;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources.NotFoundException;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationCompat.Action;
import androidx.core.app.NotificationCompat.MessagingStyle;
import androidx.core.app.Person;
import androidx.core.app.RemoteInput;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import com.android.car.apps.common.LetterTileDrawable;
import com.android.car.messenger.bluetooth.BluetoothHelper;
import com.android.car.messenger.bluetooth.BluetoothMonitor;
import com.android.car.messenger.common.ProjectionStateListener;
import com.android.car.messenger.log.L;
import com.android.car.telephony.common.TelecomUtils;
import com.android.internal.annotations.GuardedBy;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;

/** Delegate class responsible for handling messaging service actions */
public class MessengerDelegate implements BluetoothMonitor.OnBluetoothEventListener {
    private static final String TAG = "CM.MessengerDelegate";
    private static final Object mMapClientLock = new Object();

    private final Context mContext;
    @GuardedBy("mMapClientLock")
    private BluetoothMapClient mBluetoothMapClient;
    private final NotificationManager mNotificationManager;
    private final SmsDatabaseHandler mSmsDatabaseHandler;
    private final int mBitmapSize;
    private final float mCornerRadiusPercent;
    private boolean mShouldLoadExistingMessages;
    private CompletableFuture<Void> mPhoneNumberInfoFuture;

    @VisibleForTesting
    final Map<MessageKey, MapMessage> mMessages = new HashMap<>();
    @VisibleForTesting
    final Map<SenderKey, NotificationInfo> mNotificationInfos = new HashMap<>();
    // Mapping of when a device was connected via BluetoothMapClient. Used so we don't show
    // Notifications for messages received before this time.
    @VisibleForTesting
    final Map<String, Long> mBTDeviceAddressToConnectionTimestamp = new HashMap<>();
    final Map<SenderKey, Bitmap> mSenderToLargeIconBitmap = new HashMap<>();

    /** Tracks whether a projection application is active in the foreground. **/
    private ProjectionStateListener mProjectionStateListener;

    public MessengerDelegate(Context context) {
        mContext = context;

        mProjectionStateListener = new ProjectionStateListener(context);
        mProjectionStateListener.start();

        mNotificationManager =
                (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        mSmsDatabaseHandler = new SmsDatabaseHandler(mContext);

        mBitmapSize =
            mContext.getResources()
                .getDimensionPixelSize(R.dimen.notification_contact_photo_size);
        mCornerRadiusPercent = mContext.getResources()
            .getFloat(R.dimen.contact_avatar_corner_radius_percent);
        try {
            mShouldLoadExistingMessages =
                    mContext.getResources().getBoolean(R.bool.config_loadExistingMessages);
        } catch(NotFoundException e) {
            // Should only happen for robolectric unit tests;
            L.e(TAG, e, "Disabling loading of existing messages");
            mShouldLoadExistingMessages = false;
        }
    }

    @Override
    public void onMessageReceived(Intent intent) {
        try {
            MapMessage message = MapMessage.parseFrom(intent);
            if (message == null) return;
            L.d(TAG, "Received message from " + message.getDeviceAddress());

            MessageKey messageKey = new MessageKey(message);
            boolean repeatMessage = mMessages.containsKey(messageKey);
            mMessages.put(messageKey, message);
            if (!repeatMessage) {
                mSmsDatabaseHandler.addOrUpdate(message);
                updateNotification(messageKey, message);
            }
        } catch (IllegalArgumentException e) {
            L.e(TAG, e, "Dropping invalid MAP message.");
        }
    }

    @Override
    public void onMessageSent(Intent intent) {
        /* NO-OP */
    }

    @Override
    public void onDeviceConnected(BluetoothDevice device) {
        L.d(TAG, "Device connected: \t%s", device.getAddress());
        mBTDeviceAddressToConnectionTimestamp.put(device.getAddress(), System.currentTimeMillis());
        synchronized (mMapClientLock) {
            if (mBluetoothMapClient != null) {
                if (mShouldLoadExistingMessages) {
                    mBluetoothMapClient.getUnreadMessages(device);
                }
            } else {
                // onDeviceConnected should be sent by BluetoothMapClient, so log if we run into
                // this strange case.
                L.e(TAG, "BluetoothMapClient is null after connecting to device.");
            }
        }
    }

    @Override
    public void onDeviceDisconnected(BluetoothDevice device) {
        L.d(TAG, "Device disconnected: \t%s", device.getAddress());
        cleanupMessagesAndNotifications(key -> key.matches(device.getAddress()));
        mBTDeviceAddressToConnectionTimestamp.remove(device.getAddress());
        mSmsDatabaseHandler.removeMessagesForDevice(device.getAddress());
    }

    @Override
    public void onMapConnected(BluetoothMapClient client) {
        L.d(TAG, "Connected to BluetoothMapClient");
        List<BluetoothDevice> connectedDevices;
        synchronized (mMapClientLock) {
            if (mBluetoothMapClient == client) {
                return;
            }

            mBluetoothMapClient = client;
            connectedDevices = mBluetoothMapClient.getConnectedDevices();
        }
        if (connectedDevices != null) {
            for (BluetoothDevice device : connectedDevices) {
                onDeviceConnected(device);
            }
        }
    }

    @Override
    public void onMapDisconnected() {
        L.d(TAG, "Disconnected from BluetoothMapClient");
        cleanupMessagesAndNotifications(key -> true);
        synchronized (mMapClientLock) {
            mBluetoothMapClient = null;
        }
    }

    @Override
    public void onSdpRecord(BluetoothDevice device, boolean supportsReply) {
        /* NO_OP */
    }

    protected void sendMessage(SenderKey senderKey, String messageText) {
        boolean success = false;
        // Even if the device is not connected, try anyway so that the reply in enqueued.
        synchronized (mMapClientLock) {
            if (mBluetoothMapClient != null) {
                NotificationInfo notificationInfo = mNotificationInfos.get(senderKey);
                if (notificationInfo == null) {
                    L.w(TAG, "No notificationInfo found for senderKey: %s", senderKey);
                } else if (notificationInfo.mSenderContactUri == null) {
                    L.w(TAG, "Do not have contact URI for sender!");
                } else {
                    Uri[] recipientUris = {Uri.parse(notificationInfo.mSenderContactUri)};

                    final int requestCode = senderKey.hashCode();

                    Intent intent = new Intent(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY);
                    PendingIntent sentIntent = PendingIntent.getBroadcast(mContext, requestCode,
                            intent,
                            PendingIntent.FLAG_ONE_SHOT);

                    success = BluetoothHelper.sendMessage(mBluetoothMapClient,
                            senderKey.getDeviceAddress(), recipientUris, messageText,
                            sentIntent, null);
                }
            }
        }

        final boolean deviceConnected = mBTDeviceAddressToConnectionTimestamp.containsKey(
                senderKey.getDeviceAddress());
        if (!success || !deviceConnected) {
            L.e(TAG, "Unable to send reply!");
            final int toastResource = deviceConnected
                    ? R.string.auto_reply_failed_message
                    : R.string.auto_reply_device_disconnected;

            Toast.makeText(mContext, toastResource, Toast.LENGTH_SHORT).show();
        }
    }


    /**
     * Excludes messages from a notification so that the messages are not shown to the user once
     * the notification gets updated with newer messages.
     */
    protected void excludeFromNotification(SenderKey senderKey) {
        NotificationInfo info = mNotificationInfos.get(senderKey);
        for (MessageKey key : info.mMessageKeys) {
            MapMessage message = mMessages.get(key);
            if (message.shouldIncludeInNotification()) {
                message.excludeFromNotification();
                mSmsDatabaseHandler.addOrUpdate(message);
            }
        }
    }

    protected void onDestroy() {
        cleanupMessagesAndNotifications(key -> true);

        if (mPhoneNumberInfoFuture != null) {
            mPhoneNumberInfoFuture.cancel(true);
        }
        mProjectionStateListener.stop();
    }

    /**
     * Clears all notifications matching the {@param predicate}. Example method calls are when user
     * wants to clear (a) message notification(s), or when the Bluetooth device that received the
     * messages has been disconnected.
     */
    protected void clearNotifications(Predicate<CompositeKey> predicate) {
        mNotificationInfos.forEach((senderKey, notificationInfo) -> {
            if (predicate.test(senderKey)) {
                mNotificationManager.cancel(notificationInfo.mNotificationId);
            }
            excludeFromNotification(senderKey);
        });
    }

    /** Removes all messages related to the inputted predicate, and cancels their notifications. **/
    private void cleanupMessagesAndNotifications(Predicate<CompositeKey> predicate) {
        for (MessageKey key : mMessages.keySet()) {
            if (predicate.test(key)) {
                mSmsDatabaseHandler.removeMessagesForDevice(key.getDeviceAddress());
            }
        }
        clearNotifications(predicate);
        mNotificationInfos.entrySet().removeIf(entry -> predicate.test(entry.getKey()));
        mSenderToLargeIconBitmap.entrySet().removeIf(entry -> predicate.test(entry.getKey()));
        mMessages.entrySet().removeIf(
                messageKeyMapMessageEntry -> predicate.test(messageKeyMapMessageEntry.getKey()));
    }

    private void updateNotification(MessageKey messageKey, MapMessage mapMessage) {
        // Only show notifications for messages received AFTER phone was connected.
        if (mapMessage.getReceiveTime()
                < mBTDeviceAddressToConnectionTimestamp.get(mapMessage.getDeviceAddress())) {
            return;
        }

        SmsDatabaseHandler.readDatabase(mContext);
        SenderKey senderKey = new SenderKey(mapMessage);
        if (!mNotificationInfos.containsKey(senderKey)) {
            mNotificationInfos.put(senderKey, new NotificationInfo(mapMessage.getSenderName(),
                    mapMessage.getSenderContactUri()));
        }
        NotificationInfo notificationInfo = mNotificationInfos.get(senderKey);
        notificationInfo.mMessageKeys.add(messageKey);

        updateNotificationWithIcon(senderKey, notificationInfo);
    }

    private void updateNotificationWithIcon(SenderKey senderKey,
        NotificationInfo notificationInfo) {
        String phoneNumber = getPhoneNumber(notificationInfo.mSenderContactUri);
        if (mSenderToLargeIconBitmap.get(senderKey) != null || phoneNumber == null) {
            postNotification(senderKey, notificationInfo);
        }

        if (mPhoneNumberInfoFuture != null) {
            mPhoneNumberInfoFuture.cancel(/* mayInterruptRunning= */ true);
        }

        LetterTileDrawable errorDrawable = TelecomUtils.createLetterTile(mContext,
            notificationInfo.mSenderName, notificationInfo.mSenderName);

        mPhoneNumberInfoFuture = TelecomUtils.getPhoneNumberInfo(mContext, phoneNumber)
            .thenAcceptAsync(phoneNumberInfo -> {
                if (phoneNumberInfo == null) {
                    postNotification(senderKey, notificationInfo);
                }
                Glide.with(mContext)
                    .asBitmap()
                    .load(phoneNumberInfo.getAvatarUri())
                    .apply(new RequestOptions().override(mBitmapSize).error(errorDrawable))
                    .into(new SimpleTarget<Bitmap>() {
                        @Override
                        public void onResourceReady(Bitmap bitmap,
                            Transition<? super Bitmap> transition) {
                            RoundedBitmapDrawable roundedBitmapDrawable =
                                RoundedBitmapDrawableFactory
                                    .create(mContext.getResources(), bitmap);
                            Icon avatarIcon = TelecomUtils
                                .createFromRoundedBitmapDrawable(roundedBitmapDrawable, mBitmapSize,
                                    mCornerRadiusPercent);
                            mSenderToLargeIconBitmap.put(senderKey, avatarIcon.getBitmap());
                            postNotification(senderKey, notificationInfo);
                        }

                        @Override
                        public void onLoadFailed(@Nullable Drawable fallback) {
                            postNotification(senderKey, notificationInfo);
                        }

                    });
            }, mContext.getMainExecutor());
    }

    private void postNotification(SenderKey senderKey, NotificationInfo notificationInfo) {
        mNotificationManager.notify(
            notificationInfo.mNotificationId,
            createNotification(senderKey, notificationInfo));
    }

    private Notification createNotification(
        SenderKey senderKey, NotificationInfo notificationInfo) {
        String contentText = mContext.getResources().getQuantityString(
                R.plurals.notification_new_message, notificationInfo.mMessageKeys.size(),
                notificationInfo.mMessageKeys.size());
        long lastReceiveTime = mMessages.get(notificationInfo.mMessageKeys.getLast())
                .getReceiveTime();

        Bitmap largeIcon = mSenderToLargeIconBitmap.get(senderKey);
        if (largeIcon == null) {
            largeIcon =
                TelecomUtils.createLetterTile(mContext,
                    TelecomUtils.getInitials(notificationInfo.mSenderName, ""),
                    notificationInfo.mSenderName, mBitmapSize, mCornerRadiusPercent).getBitmap();
        }

        final String senderName = notificationInfo.mSenderName;
        final int notificationId = notificationInfo.mNotificationId;

        // Create the Content Intent
        PendingIntent deleteIntent = createServiceIntent(senderKey, notificationId,
                MessengerService.ACTION_CLEAR_NOTIFICATION_STATE);

        List<Action> actions = getNotificationActions(senderKey, notificationId);

        Person user = new Person.Builder()
                .setName(mContext.getString(R.string.name_not_available))
                .build();
        MessagingStyle messagingStyle = new MessagingStyle(user);
        Person sender = new Person.Builder()
                .setName(senderName)
                .setUri(notificationInfo.mSenderContactUri)
                .build();
        notificationInfo.mMessageKeys.stream().map(mMessages::get).forEachOrdered(message -> {
            if (message.shouldIncludeInNotification()) {
                messagingStyle.addMessage(
                        message.getMessageText(),
                        message.getReceiveTime(),
                        sender);
            } else {
                L.d(TAG, "excluding message received at: " + message.getReceiveTime()
                        + " from notification.");
            }
        });

        NotificationCompat.Builder builder;
        if (mProjectionStateListener.isProjectionInActiveForeground(senderKey.getDeviceAddress())) {
            builder = new NotificationCompat.Builder(mContext,
                    MessengerService.SILENT_SMS_CHANNEL_ID);
        } else {
            builder = new NotificationCompat.Builder(mContext, MessengerService.SMS_CHANNEL_ID);
        }

        builder.setContentTitle(senderName)
                .setContentText(contentText)
                .setStyle(messagingStyle)
                .setCategory(Notification.CATEGORY_MESSAGE)
                .setLargeIcon(largeIcon)
                .setSmallIcon(R.drawable.ic_message)
                .setWhen(lastReceiveTime)
                .setShowWhen(true)
                .setDeleteIntent(deleteIntent);

        for (final Action action : actions) {
            builder.addAction(action);
        }

        return builder.build();
    }

    private PendingIntent createServiceIntent(SenderKey senderKey, int notificationId,
            String action) {
        Intent intent = new Intent(mContext, MessengerService.class)
                .setAction(action)
                .putExtra(MessengerService.EXTRA_SENDER_KEY, senderKey);

        return PendingIntent.getForegroundService(mContext, notificationId, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
    }

    private List<Action> getNotificationActions(SenderKey senderKey, int notificationId) {

        final int icon = android.R.drawable.ic_media_play;

        final List<Action> actionList = new ArrayList<>();

        // Reply action
        if (shouldAddReplyAction(senderKey)) {
            final String replyString = mContext.getString(R.string.action_reply);
            PendingIntent replyIntent = createServiceIntent(senderKey, notificationId,
                    MessengerService.ACTION_VOICE_REPLY);
            actionList.add(
                    new Action.Builder(icon, replyString, replyIntent)
                            .setSemanticAction(Action.SEMANTIC_ACTION_REPLY)
                            .setShowsUserInterface(false)
                            .addRemoteInput(
                                    new RemoteInput.Builder(MessengerService.REMOTE_INPUT_KEY)
                                            .build()
                            )
                            .build()
            );
        } else {
            L.d(TAG, "Not adding Reply action for " + senderKey.getDeviceAddress());
        }

        // Mark-as-read Action. This will be the callback of Notification Center's "Read" action.
        final String markAsRead = mContext.getString(R.string.action_mark_as_read);
        PendingIntent markAsReadIntent = createServiceIntent(senderKey, notificationId,
                MessengerService.ACTION_MARK_AS_READ);
        actionList.add(
                new Action.Builder(icon, markAsRead, markAsReadIntent)
                        .setSemanticAction(Action.SEMANTIC_ACTION_MARK_AS_READ)
                        .setShowsUserInterface(false)
                        .build()
        );

        return actionList;
    }

    private boolean shouldAddReplyAction(SenderKey senderKey) {
        if (mNotificationInfos.get(senderKey).mSenderContactUri == null) {
            return false;
        }

        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (adapter == null) {
            return false;
        }
        BluetoothDevice device = adapter.getRemoteDevice(senderKey.getDeviceAddress());

        synchronized (mMapClientLock) {
            return (mBluetoothMapClient != null) && mBluetoothMapClient.isUploadingSupported(
                    device);
        }
    }

    /**
     * Extracts the phone number from the {@link BluetoothMapClient} formatted URI.
     **/
    @Nullable
    private String getPhoneNumber(String senderContactUri) {
        if (senderContactUri == null || !senderContactUri.matches("tel:(.+)")) {
            return null;
        }

        return senderContactUri.substring(4);
    }

    /**
     * Contains information about a single notification that is displayed, with grouped messages.
     */
    @VisibleForTesting
    static class NotificationInfo {
        private static int NEXT_NOTIFICATION_ID = 0;

        final int mNotificationId = NEXT_NOTIFICATION_ID++;
        final String mSenderName;
        @Nullable
        final String mSenderContactUri;
        final LinkedList<MessageKey> mMessageKeys = new LinkedList<>();

        NotificationInfo(String senderName, @Nullable String senderContactUri) {
            mSenderName = senderName;
            mSenderContactUri = senderContactUri;
        }
    }

    /**
     * {@link CompositeKey} subclass used to identify specific messages; it uses message-handle as
     * the secondary key.
     */
    public static class MessageKey extends CompositeKey {
        MessageKey(MapMessage message) {
            super(message.getDeviceAddress(), message.getHandle());
        }
    }
}
