/*
 * Copyright (C) 2019 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.messenger.common;

import static com.android.car.apps.common.util.SafeLog.logw;

import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.text.BidiFormatter;
import android.text.TextDirectionHeuristics;
import android.text.TextUtils;

import androidx.annotation.Nullable;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;

import com.android.car.apps.common.LetterTileDrawable;
import com.android.car.messenger.NotificationMsgProto.NotificationMsg;
import com.android.car.messenger.NotificationMsgProto.NotificationMsg.AvatarIconSync;
import com.android.car.messenger.NotificationMsgProto.NotificationMsg.ConversationNotification;
import com.android.car.messenger.NotificationMsgProto.NotificationMsg.MessagingStyle;
import com.android.car.messenger.NotificationMsgProto.NotificationMsg.MessagingStyleMessage;
import com.android.car.messenger.NotificationMsgProto.NotificationMsg.Person;

import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/** Utils methods for the car-messenger-common lib. **/
public class Utils {
    private static final String TAG = "CMC.Utils";
    /**
     * Represents the maximum length of a message substring to be used when constructing the
     * message's unique handle/key.
     */
    private static final int MAX_SUB_MESSAGE_LENGTH = 5;

    /** The Regex format of a telephone number in a BluetoothMapClient contact URI. **/
    private static final String MAP_CLIENT_URI_REGEX = "tel:(.+)";

    /** The starting substring index for a string formatted with the MAP_CLIENT_URI_REGEX above. **/
    private static final int MAP_CLIENT_URI_PHONE_NUMBER_SUBSTRING_INDEX = 4;

    // TODO (150711637): Reference BluetoothMapClient Extras once BluetoothMapClient is SystemApi.
    protected static final String BMC_EXTRA_MESSAGE_HANDLE =
            "android.bluetooth.mapmce.profile.extra.MESSAGE_HANDLE";
    protected static final String BMC_EXTRA_SENDER_CONTACT_URI =
            "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_URI";
    protected static final String BMC_EXTRA_SENDER_CONTACT_NAME =
            "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
    protected static final String BMC_EXTRA_MESSAGE_TIMESTAMP =
            "android.bluetooth.mapmce.profile.extra.MESSAGE_TIMESTAMP";
    protected static final String BMC_EXTRA_MESSAGE_READ_STATUS =
            "android.bluetooth.mapmce.profile.extra.MESSAGE_READ_STATUS";

    /** Gets the latest message for a {@link NotificationMsg} Conversation. **/
    public static MessagingStyleMessage getLatestMessage(
            ConversationNotification notification) {
        MessagingStyle messagingStyle = notification.getMessagingStyle();
        long latestTime = 0;
        MessagingStyleMessage latestMessage = null;

        for (MessagingStyleMessage message : messagingStyle.getMessagingStyleMsgList()) {
            if (message.getTimestamp() > latestTime) {
                latestTime = message.getTimestamp();
                latestMessage = message;
            }
        }
        return latestMessage;
    }

    /**
     * Helper method to create a unique handle/key for this message. This is used as this Message's
     * {@link MessageKey#getSubKey()}.
     */
    public static String createMessageHandle(MessagingStyleMessage message) {
        String textMessage = message.getTextMessage();
        String subMessage = textMessage.substring(
                Math.min(MAX_SUB_MESSAGE_LENGTH, textMessage.length()));
        return message.getTimestamp() + "/" + message.getSender().getName() + "/" + subMessage;
    }

    /**
     * Ensure the {@link ConversationNotification} object has all the required fields.
     *
     * @param isShallowCheck should be {@code true} if the caller only wants to verify the
     *                       notification and its {@link MessagingStyle} is valid, without checking
     *                       all of the notification's {@link MessagingStyleMessage}s.
     **/
    public static boolean isValidConversationNotification(ConversationNotification notification,
            boolean isShallowCheck) {
        if (notification == null) {
            logw(TAG, "ConversationNotification is null");
            return false;
        } else if (!notification.hasMessagingStyle()) {
            logw(TAG, "ConversationNotification is missing required field: messagingStyle");
            return false;
        } else if (notification.getMessagingAppDisplayName() == null) {
            logw(TAG, "ConversationNotification is missing required field: appDisplayName");
            return false;
        } else if (notification.getMessagingAppPackageName() == null) {
            logw(TAG, "ConversationNotification is missing required field: appPackageName");
            return false;
        }
        return isValidMessagingStyle(notification.getMessagingStyle(), isShallowCheck);
    }

    /**
     * Ensure the {@link MessagingStyle} object has all the required fields.
     **/
    private static boolean isValidMessagingStyle(MessagingStyle messagingStyle,
            boolean isShallowCheck) {
        if (messagingStyle == null) {
            logw(TAG, "MessagingStyle is null");
            return false;
        } else if (messagingStyle.getConvoTitle() == null) {
            logw(TAG, "MessagingStyle is missing required field: convoTitle");
            return false;
        } else if (messagingStyle.getUserDisplayName() == null) {
            logw(TAG, "MessagingStyle is missing required field: userDisplayName");
            return false;
        } else if (messagingStyle.getMessagingStyleMsgCount() == 0) {
            logw(TAG, "MessagingStyle is missing required field: messagingStyleMsg");
            return false;
        }
        if (!isShallowCheck) {
            for (MessagingStyleMessage message : messagingStyle.getMessagingStyleMsgList()) {
                if (!isValidMessagingStyleMessage(message)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Ensure the {@link MessagingStyleMessage} object has all the required fields.
     **/
    public static boolean isValidMessagingStyleMessage(MessagingStyleMessage message) {
        if (message == null) {
            logw(TAG, "MessagingStyleMessage is null");
            return false;
        } else if (message.getTextMessage() == null) {
            logw(TAG, "MessagingStyleMessage is missing required field: textMessage");
            return false;
        } else if (!message.hasSender()) {
            logw(TAG, "MessagingStyleMessage is missing required field: sender");
            return false;
        }
        return isValidSender(message.getSender());
    }

    /**
     * Ensure the {@link Person} object has all the required fields.
     **/
    public static boolean isValidSender(Person person) {
        if (person.getName() == null) {
            logw(TAG, "Person is missing required field: name");
            return false;
        }
        return true;
    }

    /**
     * Ensure the {@link AvatarIconSync} object has all the required fields.
     **/
    public static boolean isValidAvatarIconSync(AvatarIconSync iconSync) {
        if (iconSync == null) {
            logw(TAG, "AvatarIconSync is null");
            return false;
        } else if (iconSync.getMessagingAppPackageName() == null) {
            logw(TAG, "AvatarIconSync is missing required field: appPackageName");
            return false;
        } else if (iconSync.getPerson().getName() == null) {
            logw(TAG, "AvatarIconSync is missing required field: Person's name");
            return false;
        } else if (iconSync.getPerson().getAvatar() == null) {
            logw(TAG, "AvatarIconSync is missing required field: Person's avatar");
            return false;
        }
        return true;
    }

    /**
     * Ensure the BluetoothMapClient intent has all the required fields.
     **/
    public static boolean isValidMapClientIntent(Intent intent) {
        if (intent == null) {
            logw(TAG, "BluetoothMapClient intent is null");
            return false;
        } else if (intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) == null) {
            logw(TAG, "BluetoothMapClient intent is missing required field: device");
            return false;
        } else if (intent.getStringExtra(BMC_EXTRA_MESSAGE_HANDLE) == null) {
            logw(TAG, "BluetoothMapClient intent is missing required field: senderName");
            return false;
        } else if (intent.getStringExtra(BMC_EXTRA_SENDER_CONTACT_NAME) == null) {
            logw(TAG, "BluetoothMapClient intent is missing required field: handle");
            return false;
        } else if (intent.getStringExtra(android.content.Intent.EXTRA_TEXT) == null) {
            logw(TAG, "BluetoothMapClient intent is missing required field: messageText");
            return false;
        }
        return true;
    }

    /**
     * Creates a Letter Tile Icon that will display the given initials. If the initials are null,
     * then an avatar anonymous icon will be drawn.
     **/
    public static Bitmap createLetterTile(Context context, @Nullable String initials,
            String identifier, int avatarSize, float cornerRadiusPercent) {
        // TODO(b/135446418): use TelecomUtils once car-telephony-common supports bp.
        LetterTileDrawable letterTileDrawable = createLetterTileDrawable(context, initials,
                identifier);
        RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(
                context.getResources(), letterTileDrawable.toBitmap(avatarSize));
        return createFromRoundedBitmapDrawable(roundedBitmapDrawable, avatarSize,
                cornerRadiusPercent);
    }

    /** Creates an Icon based on the given roundedBitmapDrawable. **/
    private static Bitmap createFromRoundedBitmapDrawable(
            RoundedBitmapDrawable roundedBitmapDrawable, int avatarSize,
            float cornerRadiusPercent) {
        // TODO(b/135446418): use TelecomUtils once car-telephony-common supports bp.
        float radius = avatarSize * cornerRadiusPercent;
        roundedBitmapDrawable.setCornerRadius(radius);

        final Bitmap result = Bitmap.createBitmap(avatarSize, avatarSize,
                Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(result);
        roundedBitmapDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        roundedBitmapDrawable.draw(canvas);
        return roundedBitmapDrawable.getBitmap();
    }


    /**
     * Create a {@link LetterTileDrawable} for the given initials.
     *
     * @param initials   is the letters that will be drawn on the canvas. If it is null, then an
     *                   avatar anonymous icon will be drawn
     * @param identifier will decide the color for the drawable. If null, a default color will be
     *                   used.
     */
    private static LetterTileDrawable createLetterTileDrawable(
            Context context,
            @Nullable String initials,
            @Nullable String identifier) {
        // TODO(b/135446418): use TelecomUtils once car-telephony-common supports bp.
        int numberOfLetter = context.getResources().getInteger(
                R.integer.config_number_of_letters_shown_for_avatar);
        String letters = initials != null
                ? initials.substring(0, Math.min(initials.length(), numberOfLetter)) : null;
        LetterTileDrawable letterTileDrawable = new LetterTileDrawable(context.getResources(),
                letters, identifier);
        return letterTileDrawable;
    }

    /** Returns whether the BluetoothMapClient intent represents a group conversation. **/
    public static boolean isGroupConversation(Intent intent) {
        return (intent.getStringArrayExtra(Intent.EXTRA_CC) != null
                && intent.getStringArrayExtra(Intent.EXTRA_CC).length > 1);
    }

    /**
     * Returns the initials based on the name and nameAlt.
     *
     * @param name    should be the display name of a contact.
     * @param nameAlt should be alternative display name of a contact.
     */
    public static String getInitials(String name, String nameAlt) {
        // TODO(b/135446418): use TelecomUtils once car-telephony-common supports bp.
        StringBuilder initials = new StringBuilder();
        if (!TextUtils.isEmpty(name) && Character.isLetter(name.charAt(0))) {
            initials.append(Character.toUpperCase(name.charAt(0)));
        }
        if (!TextUtils.isEmpty(nameAlt)
                && !TextUtils.equals(name, nameAlt)
                && Character.isLetter(nameAlt.charAt(0))) {
            initials.append(Character.toUpperCase(nameAlt.charAt(0)));
        }
        return initials.toString();
    }

    /** Returns the list of sender uri for a BluetoothMapClient intent. **/
    public static String getSenderUri(Intent intent) {
        return intent.getStringExtra(BMC_EXTRA_SENDER_CONTACT_URI);
    }

    /** Returns the sender name for a BluetoothMapClient intent. **/
    public static String getSenderName(Intent intent) {
        return intent.getStringExtra(BMC_EXTRA_SENDER_CONTACT_NAME);
    }

    /** Returns the list of recipient uris for a BluetoothMapClient intent. **/
    public static List<String> getInclusiveRecipientsUrisList(Intent intent) {
        List<String> ccUris = new ArrayList<>();
        String uri = getSenderUri(intent);
        if (isGroupConversation(intent)) {
            ccUris.addAll(Arrays.asList(intent.getStringArrayExtra(Intent.EXTRA_CC)));
        }
        if (!ccUris.contains(uri)) {
            ccUris.add(uri);
        }

        return ccUris;
    }

    /**
     * Extracts the phone number from the BluetoothMapClient contact Uri.
     **/
    @Nullable
    public static String getPhoneNumberFromMapClient(@Nullable String senderContactUri) {
        if (senderContactUri == null || !senderContactUri.matches(MAP_CLIENT_URI_REGEX)) {
            logw(TAG, " contactUri is malformed! " + senderContactUri);
            return null;
        }

        return senderContactUri.substring(MAP_CLIENT_URI_PHONE_NUMBER_SUBSTRING_INDEX);
    }

    /**
     * Creates a Header for a group conversation, where the senderName and groupName are both shown,
     * separated by a delimiter.
     *
     * @param senderName Sender's name.
     * @param groupName  Group conversation's name.
     * @param delimiter  delimiter that separates each element.
     */
    public static String constructGroupConversationHeader(String senderName, String groupName,
            String delimiter) {
        return constructGroupConversationHeader(senderName, groupName, delimiter,
                BidiFormatter.getInstance());
    }

    /**
     * Creates a Header for a group conversation, where the senderName and groupName are both shown,
     * separated by a delimiter.
     *
     * @param senderName Sender's name.
     * @param groupName  Group conversation's name.
     * @param delimiter  delimiter that separates each element.
     * @param bidiFormatter  formatter for the context's locale.
     */
    public static String constructGroupConversationHeader(String senderName, String groupName,
            String delimiter, BidiFormatter bidiFormatter) {
        String formattedSenderName = bidiFormatter.unicodeWrap(senderName,
                TextDirectionHeuristics.FIRSTSTRONG_LTR, /* isolate= */ true);
        String formattedGroupName = bidiFormatter.unicodeWrap(groupName,
                TextDirectionHeuristics.FIRSTSTRONG_LTR, /* isolate= */ true);
        String title = String.join(delimiter, formattedSenderName, formattedGroupName);
        return bidiFormatter.unicodeWrap(title, TextDirectionHeuristics.LOCALE);
    }

    /**
     * Given a name of all the participants in a group conversation (some names might be phone
     * numbers), this function creates the conversation title by putting the names in alphabetical
     * order first, then adding any phone numbers. This title should not exceed the
     * conversationTitleLength, so not all participants' names are guaranteed to be
     * in the conversation title.
     */
    public static String constructGroupConversationTitle(List<String> names, String delimiter,
            int conversationTitleLength) {
        return constructGroupConversationTitle(names, delimiter, conversationTitleLength,
                BidiFormatter.getInstance());
    }

    /**
     * Given a name of all the participants in a group conversation (some names might be phone
     * numbers), this function creates the conversation title by putting the names in alphabetical
     * order first, then adding any phone numbers. This title should not exceed the
     * conversationTitleLength, so not all participants' names are guaranteed to be
     * in the conversation title.
     */
    public static String constructGroupConversationTitle(List<String> names, String delimiter,
            int conversationTitleLength, BidiFormatter bidiFormatter) {
        List<String> sortedNames = getSortedSubsetNames(names, conversationTitleLength,
                delimiter.length());
        String formattedDelimiter = bidiFormatter.unicodeWrap(delimiter,
                TextDirectionHeuristics.LOCALE);

        String conversationName = sortedNames.stream().map(name -> bidiFormatter.unicodeWrap(name,
                TextDirectionHeuristics.FIRSTSTRONG_LTR))
                .collect(Collectors.joining(formattedDelimiter));
        return bidiFormatter.unicodeWrap(conversationName, TextDirectionHeuristics.LOCALE);
    }

    /**
     * Sorts the list, and returns the first elements whose total length is less than the given
     * conversationTitleLength.
     */
    private static List<String> getSortedSubsetNames(List<String> names,
            int conversationTitleLength,
            int delimiterLength) {
        Collections.sort(names, Utils.ALPHA_THEN_NUMERIC_COMPARATOR);
        int namesCounter = 0;
        int indexCounter = 0;
        while (namesCounter < conversationTitleLength && indexCounter < names.size()) {
            namesCounter = namesCounter + names.get(indexCounter).length() + delimiterLength;
            indexCounter = indexCounter + 1;
        }
        return names.subList(0, indexCounter);
    }

    /** Comparator that sorts names alphabetically first, then phone numbers numerically. **/
    public static final Comparator<String> ALPHA_THEN_NUMERIC_COMPARATOR =
            new Comparator<String>() {
                private boolean isPhoneNumber(String input) {
                    PhoneNumberUtil util = PhoneNumberUtil.getInstance();
                    try {
                        Phonenumber.PhoneNumber phoneNumber = util.parse(input, /* defaultRegion */
                                null);
                        return util.isValidNumber(phoneNumber);
                    } catch (NumberParseException e) {
                        // Phone numbers without country codes should still be classified as
                        // phone numbers.
                        return e.getErrorType().equals(
                                NumberParseException.ErrorType.INVALID_COUNTRY_CODE);
                    }
                }

                private boolean isOfSameType(String o1, String o2) {
                    boolean isO1PhoneNumber = isPhoneNumber(o1);
                    boolean isO2PhoneNumber = isPhoneNumber(o2);
                    return isO1PhoneNumber == isO2PhoneNumber;
                }

                @Override
                public int compare(String o1, String o2) {
                    // if both are names, sort based on names.
                    // if both are number, sort numerically.
                    // if one is phone number and the other is a name, give name precedence.
                    if (!isOfSameType(o1, o2)) {
                        return isPhoneNumber(o1) ? 1 : -1;
                    } else {
                        return o1.compareTo(o2);
                    }
                }
            };

}
