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

import static android.telecom.Call.Details.PROPERTY_HIGH_DEF_AUDIO;
import static com.android.contacts.common.compat.CallCompat.Details.PROPERTY_ENTERPRISE_CALL;
import static com.android.incallui.NotificationBroadcastReceiver.ACTION_ACCEPT_VIDEO_UPGRADE_REQUEST;
import static com.android.incallui.NotificationBroadcastReceiver.ACTION_ANSWER_SPEAKEASY_CALL;
import static com.android.incallui.NotificationBroadcastReceiver.ACTION_ANSWER_VIDEO_INCOMING_CALL;
import static com.android.incallui.NotificationBroadcastReceiver.ACTION_ANSWER_VOICE_INCOMING_CALL;
import static com.android.incallui.NotificationBroadcastReceiver.ACTION_DECLINE_INCOMING_CALL;
import static com.android.incallui.NotificationBroadcastReceiver.ACTION_DECLINE_VIDEO_UPGRADE_REQUEST;
import static com.android.incallui.NotificationBroadcastReceiver.ACTION_HANG_UP_ONGOING_CALL;
import static com.android.incallui.NotificationBroadcastReceiver.ACTION_TURN_OFF_SPEAKER;
import static com.android.incallui.NotificationBroadcastReceiver.ACTION_TURN_ON_SPEAKER;

import android.Manifest;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Trace;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresPermission;
import android.support.annotation.StringRes;
import android.support.annotation.VisibleForTesting;
import android.support.v4.os.BuildCompat;
import android.telecom.Call.Details;
import android.telecom.CallAudioState;
import android.telecom.PhoneAccount;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.text.BidiFormatter;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextDirectionHeuristics;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import com.android.contacts.common.ContactsUtils;
import com.android.contacts.common.ContactsUtils.UserType;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.configprovider.ConfigProviderComponent;
import com.android.dialer.contactphoto.BitmapUtil;
import com.android.dialer.contacts.ContactsComponent;
import com.android.dialer.enrichedcall.EnrichedCallManager;
import com.android.dialer.enrichedcall.Session;
import com.android.dialer.lettertile.LetterTileDrawable;
import com.android.dialer.lettertile.LetterTileDrawable.ContactType;
import com.android.dialer.multimedia.MultimediaData;
import com.android.dialer.notification.NotificationChannelId;
import com.android.dialer.oem.MotorolaUtils;
import com.android.dialer.theme.base.ThemeComponent;
import com.android.dialer.util.DrawableConverter;
import com.android.incallui.ContactInfoCache.ContactCacheEntry;
import com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
import com.android.incallui.InCallPresenter.InCallState;
import com.android.incallui.async.PausableExecutorImpl;
import com.android.incallui.audiomode.AudioModeProvider;
import com.android.incallui.call.CallList;
import com.android.incallui.call.DialerCall;
import com.android.incallui.call.DialerCallListener;
import com.android.incallui.call.TelecomAdapter;
import com.android.incallui.call.state.DialerCallState;
import com.android.incallui.ringtone.DialerRingtoneManager;
import com.android.incallui.ringtone.InCallTonePlayer;
import com.android.incallui.ringtone.ToneGeneratorFactory;
import com.android.incallui.speakeasy.SpeakEasyComponent;
import com.android.incallui.videotech.utils.SessionModificationState;
import java.util.Objects;
import java.util.Optional;

/** This class adds Notifications to the status bar for the in-call experience. */
public class StatusBarNotifier
    implements InCallPresenter.InCallStateListener,
        EnrichedCallManager.StateChangedListener,
        ContactInfoCacheCallback {

  private static final int NOTIFICATION_ID = 1;

  // Notification types
  // Indicates that no notification is currently showing.
  private static final int NOTIFICATION_NONE = 0;
  // Notification for an active call. This is non-interruptive, but cannot be dismissed.
  private static final int NOTIFICATION_IN_CALL = 1;
  // Notification for incoming calls. This is interruptive and will show up as a HUN.
  private static final int NOTIFICATION_INCOMING_CALL = 2;
  // Notification for incoming calls in the case where there is already an active call.
  // This is non-interruptive, but otherwise behaves the same as NOTIFICATION_INCOMING_CALL
  private static final int NOTIFICATION_INCOMING_CALL_QUIET = 3;

  private static final long[] VIBRATE_PATTERN = new long[] {0, 1000, 1000};

  private final Context context;
  private final ContactInfoCache contactInfoCache;
  private final DialerRingtoneManager dialerRingtoneManager;
  private int currentNotification = NOTIFICATION_NONE;
  private int callState = DialerCallState.INVALID;
  private int videoState = VideoProfile.STATE_AUDIO_ONLY;
  private int savedIcon = 0;
  private String savedContent = null;
  private Bitmap savedLargeIcon;
  private String savedContentTitle;
  private CallAudioState savedCallAudioState;
  private Uri ringtone;
  private StatusBarCallListener statusBarCallListener;

  public StatusBarNotifier(@NonNull Context context, @NonNull ContactInfoCache contactInfoCache) {
    Trace.beginSection("StatusBarNotifier.Constructor");
    this.context = Assert.isNotNull(context);
    this.contactInfoCache = contactInfoCache;
    dialerRingtoneManager =
        new DialerRingtoneManager(
            new InCallTonePlayer(new ToneGeneratorFactory(), new PausableExecutorImpl()),
            CallList.getInstance());
    currentNotification = NOTIFICATION_NONE;
    Trace.endSection();
  }

  /**
   * Should only be called from a irrecoverable state where it is necessary to dismiss all
   * notifications.
   */
  static void clearAllCallNotifications() {
    LogUtil.e(
        "StatusBarNotifier.clearAllCallNotifications",
        "something terrible happened, clear all InCall notifications");

    TelecomAdapter.getInstance().stopForegroundNotification();
  }

  private static int getWorkStringFromPersonalString(int resId) {
    if (resId == R.string.notification_ongoing_call) {
      return R.string.notification_ongoing_work_call;
    } else if (resId == R.string.notification_incoming_call) {
      return R.string.notification_incoming_work_call;
    } else {
      return resId;
    }
  }

  /**
   * Returns PendingIntent for answering a phone call. This will typically be used from Notification
   * context.
   */
  private static PendingIntent createNotificationPendingIntent(Context context, String action) {
    final Intent intent = new Intent(action, null, context, NotificationBroadcastReceiver.class);
    return PendingIntent.getBroadcast(context, 0, intent, 0);
  }

  /** Creates notifications according to the state we receive from {@link InCallPresenter}. */
  @Override
  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
  public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
    LogUtil.d("StatusBarNotifier.onStateChange", "%s->%s", oldState, newState);
    updateNotification();
  }

  @Override
  public void onEnrichedCallStateChanged() {
    LogUtil.enterBlock("StatusBarNotifier.onEnrichedCallStateChanged");
    updateNotification();
  }

  /**
   * Updates the phone app's status bar notification *and* launches the incoming call UI in response
   * to a new incoming call.
   *
   * <p>If an incoming call is ringing (or call-waiting), the notification will also include a
   * "fullScreenIntent" that will cause the InCallScreen to be launched, unless the current
   * foreground activity is marked as "immersive".
   *
   * <p>(This is the mechanism that actually brings up the incoming call UI when we receive a "new
   * ringing connection" event from the telephony layer.)
   *
   * <p>Also note that this method is safe to call even if the phone isn't actually ringing (or,
   * more likely, if an incoming call *was* ringing briefly but then disconnected). In that case,
   * we'll simply update or cancel the in-call notification based on the current phone state.
   *
   * @see #updateInCallNotification()
   */
  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
  public void updateNotification() {
    updateInCallNotification();
  }

  /**
   * Take down the in-call notification.
   *
   * @see #updateInCallNotification()
   */
  private void cancelNotification() {
    if (statusBarCallListener != null) {
      setStatusBarCallListener(null);
    }
    if (currentNotification != NOTIFICATION_NONE) {
      TelecomAdapter.getInstance().stopForegroundNotification();
      currentNotification = NOTIFICATION_NONE;
    }
  }

  /**
   * Helper method for updateInCallNotification() and updateNotification(): Update the phone app's
   * status bar notification based on the current telephony state, or cancels the notification if
   * the phone is totally idle.
   */
  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
  private void updateInCallNotification() {
    LogUtil.d("StatusBarNotifier.updateInCallNotification", "");

    final DialerCall call = getCallToShow(CallList.getInstance());

    if (call != null) {
      showNotification(call);
    } else {
      cancelNotification();
    }
  }

  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
  private void showNotification(final DialerCall call) {
    Trace.beginSection("StatusBarNotifier.showNotification");
    final boolean isIncoming =
        (call.getState() == DialerCallState.INCOMING
            || call.getState() == DialerCallState.CALL_WAITING);
    setStatusBarCallListener(new StatusBarCallListener(call));

    // we make a call to the contact info cache to query for supplemental data to what the
    // call provides.  This includes the contact name and photo.
    // This callback will always get called immediately and synchronously with whatever data
    // it has available, and may make a subsequent call later (same thread) if it had to
    // call into the contacts provider for more data.
    contactInfoCache.findInfo(call, isIncoming, this);
    Trace.endSection();
  }

  /** Sets up the main Ui for the notification */
  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
  private void buildAndSendNotification(
      CallList callList, DialerCall originalCall, ContactCacheEntry contactInfo) {
    Trace.beginSection("StatusBarNotifier.buildAndSendNotification");
    // This can get called to update an existing notification after contact information has come
    // back. However, it can happen much later. Before we continue, we need to make sure that
    // the call being passed in is still the one we want to show in the notification.
    final DialerCall call = getCallToShow(callList);
    if (call == null || !call.getId().equals(originalCall.getId())) {
      Trace.endSection();
      return;
    }

    Trace.beginSection("prepare work");
    final int callState = call.getState();
    final CallAudioState callAudioState = AudioModeProvider.getInstance().getAudioState();

    Trace.beginSection("read icon and strings");
    // Check if data has changed; if nothing is different, don't issue another notification.
    final int iconResId = getIconToDisplay(call);
    Bitmap largeIcon = getLargeIconToDisplay(context, contactInfo, call);
    final CharSequence content = getContentString(call, contactInfo.userType);
    final String contentTitle = getContentTitle(contactInfo, call);
    Trace.endSection();

    final boolean isVideoUpgradeRequest =
        call.getVideoTech().getSessionModificationState()
            == SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST;
    final int notificationType;
    if (callState == DialerCallState.INCOMING
        || callState == DialerCallState.CALL_WAITING
        || isVideoUpgradeRequest) {
      if (ConfigProviderComponent.get(context)
          .getConfigProvider()
          .getBoolean("quiet_incoming_call_if_ui_showing", true)) {
        notificationType =
            InCallPresenter.getInstance().isShowingInCallUi()
                ? NOTIFICATION_INCOMING_CALL_QUIET
                : NOTIFICATION_INCOMING_CALL;
      } else {
        boolean alreadyActive =
            callList.getActiveOrBackgroundCall() != null
                && InCallPresenter.getInstance().isShowingInCallUi();
        notificationType =
            alreadyActive ? NOTIFICATION_INCOMING_CALL_QUIET : NOTIFICATION_INCOMING_CALL;
      }
    } else {
      notificationType = NOTIFICATION_IN_CALL;
    }
    Trace.endSection(); // prepare work

    if (!checkForChangeAndSaveData(
        iconResId,
        content.toString(),
        largeIcon,
        contentTitle,
        callState,
        call.getVideoState(),
        notificationType,
        contactInfo.contactRingtoneUri,
        callAudioState)) {
      Trace.endSection();
      return;
    }

    if (largeIcon != null) {
      largeIcon = getRoundedIcon(largeIcon);
    }

    // This builder is used for the notification shown when the device is locked and the user
    // has set their notification settings to 'hide sensitive content'
    // {@see Notification.Builder#setPublicVersion}.
    Notification.Builder publicBuilder = new Notification.Builder(context);
    publicBuilder
        .setSmallIcon(iconResId)
        .setColor(ThemeComponent.get(context).theme().getColorPrimary())
        // Hide work call state for the lock screen notification
        .setContentTitle(getContentString(call, ContactsUtils.USER_TYPE_CURRENT));
    setNotificationWhen(call, callState, publicBuilder);

    // Builder for the notification shown when the device is unlocked or the user has set their
    // notification settings to 'show all notification content'.
    final Notification.Builder builder = getNotificationBuilder();
    builder.setPublicVersion(publicBuilder.build());

    // Set up the main intent to send the user to the in-call screen
    builder.setContentIntent(createLaunchPendingIntent(false /* isFullScreen */));

    LogUtil.i("StatusBarNotifier.buildAndSendNotification", "notificationType=" + notificationType);
    switch (notificationType) {
      case NOTIFICATION_INCOMING_CALL:
        if (BuildCompat.isAtLeastO()) {
          builder.setChannelId(NotificationChannelId.INCOMING_CALL);
        }
        // Set the intent as a full screen intent as well if a call is incoming
        configureFullScreenIntent(builder, createLaunchPendingIntent(true /* isFullScreen */));
        // Set the notification category and bump the priority for incoming calls
        builder.setCategory(Notification.CATEGORY_CALL);
        // This will be ignored on O+ and handled by the channel
        builder.setPriority(Notification.PRIORITY_MAX);
        if (currentNotification != NOTIFICATION_INCOMING_CALL) {
          LogUtil.i(
              "StatusBarNotifier.buildAndSendNotification",
              "Canceling old notification so this one can be noisy");
          // Moving from a non-interuptive notification (or none) to a noisy one. Cancel the old
          // notification (if there is one) so the fullScreenIntent or HUN will show
          TelecomAdapter.getInstance().stopForegroundNotification();
        }
        break;
      case NOTIFICATION_INCOMING_CALL_QUIET:
        if (BuildCompat.isAtLeastO()) {
          builder.setChannelId(NotificationChannelId.ONGOING_CALL);
        }
        break;
      case NOTIFICATION_IN_CALL:
        if (BuildCompat.isAtLeastO()) {
          publicBuilder.setColorized(true);
          builder.setColorized(true);
          builder.setChannelId(NotificationChannelId.ONGOING_CALL);
        }
        break;
      default:
        break;
    }

    // Set the content
    builder.setContentText(content);
    builder.setSmallIcon(iconResId);
    builder.setContentTitle(contentTitle);
    builder.setLargeIcon(largeIcon);
    builder.setColor(InCallPresenter.getInstance().getThemeColorManager().getPrimaryColor());

    if (isVideoUpgradeRequest) {
      builder.setUsesChronometer(false);
      addDismissUpgradeRequestAction(builder);
      addAcceptUpgradeRequestAction(builder);
    } else {
      createIncomingCallNotification(call, callState, callAudioState, builder);
    }

    addPersonReference(builder, contactInfo, call);

    Trace.beginSection("fire notification");
    // Fire off the notification
    Notification notification = builder.build();

    if (dialerRingtoneManager.shouldPlayRingtone(callState, contactInfo.contactRingtoneUri)) {
      notification.flags |= Notification.FLAG_INSISTENT;
      notification.sound = contactInfo.contactRingtoneUri;
      AudioAttributes.Builder audioAttributes = new AudioAttributes.Builder();
      audioAttributes.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC);
      audioAttributes.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
      notification.audioAttributes = audioAttributes.build();
      if (dialerRingtoneManager.shouldVibrate(context.getContentResolver())) {
        notification.vibrate = VIBRATE_PATTERN;
      }
    }
    if (dialerRingtoneManager.shouldPlayCallWaitingTone(callState)) {
      LogUtil.v("StatusBarNotifier.buildAndSendNotification", "playing call waiting tone");
      dialerRingtoneManager.playCallWaitingTone();
    }

    LogUtil.i(
        "StatusBarNotifier.buildAndSendNotification",
        "displaying notification for " + notificationType);

    // If a notification exists, this will only update it.
    TelecomAdapter.getInstance().startForegroundNotification(NOTIFICATION_ID, notification);

    Trace.endSection();
    call.getLatencyReport().onNotificationShown();
    currentNotification = notificationType;
    Trace.endSection();
  }

  private void createIncomingCallNotification(
      DialerCall call, int state, CallAudioState callAudioState, Notification.Builder builder) {
    setNotificationWhen(call, state, builder);

    // Add hang up option for any active calls (active | onhold), outgoing calls (dialing).
    if (state == DialerCallState.ACTIVE
        || state == DialerCallState.ONHOLD
        || DialerCallState.isDialing(state)) {
      addHangupAction(builder);
      addSpeakerAction(builder, callAudioState);
    } else if (state == DialerCallState.INCOMING || state == DialerCallState.CALL_WAITING) {
      addDismissAction(builder);
      if (call.isVideoCall()) {
        addVideoCallAction(builder);
      } else {
        addAnswerAction(builder);
        addSpeakeasyAnswerAction(builder, call);
      }
    }
  }

  /**
   * Sets the notification's when section as needed. For active calls, this is explicitly set as the
   * duration of the call. For all other states, the notification will automatically show the time
   * at which the notification was created.
   */
  private void setNotificationWhen(DialerCall call, int state, Notification.Builder builder) {
    if (state == DialerCallState.ACTIVE) {
      builder.setUsesChronometer(true);
      builder.setWhen(call.getConnectTimeMillis());
    } else {
      builder.setUsesChronometer(false);
    }
  }

  /**
   * Checks the new notification data and compares it against any notification that we are already
   * displaying. If the data is exactly the same, we return false so that we do not issue a new
   * notification for the exact same data.
   */
  private boolean checkForChangeAndSaveData(
      int icon,
      String content,
      Bitmap largeIcon,
      String contentTitle,
      int state,
      int videoState,
      int notificationType,
      Uri ringtone,
      CallAudioState callAudioState) {

    // The two are different:
    // if new title is not null, it should be different from saved version OR
    // if new title is null, the saved version should not be null
    final boolean contentTitleChanged =
        (contentTitle != null && !contentTitle.equals(savedContentTitle))
            || (contentTitle == null && savedContentTitle != null);

    boolean largeIconChanged;
    if (savedLargeIcon == null) {
      largeIconChanged = largeIcon != null;
    } else {
      largeIconChanged = largeIcon == null || !savedLargeIcon.sameAs(largeIcon);
    }

    // any change means we are definitely updating
    boolean retval =
        (savedIcon != icon)
            || !Objects.equals(savedContent, content)
            || (callState != state)
            || (this.videoState != videoState)
            || largeIconChanged
            || contentTitleChanged
            || !Objects.equals(this.ringtone, ringtone)
            || !Objects.equals(savedCallAudioState, callAudioState);

    LogUtil.d(
        "StatusBarNotifier.checkForChangeAndSaveData",
        "data changed: icon: %b, content: %b, state: %b, videoState: %b, largeIcon: %b, title: %b,"
            + "ringtone: %b, audioState: %b, type: %b",
        (savedIcon != icon),
        !Objects.equals(savedContent, content),
        (callState != state),
        (this.videoState != videoState),
        largeIconChanged,
        contentTitleChanged,
        !Objects.equals(this.ringtone, ringtone),
        !Objects.equals(savedCallAudioState, callAudioState),
        currentNotification != notificationType);
    // If we aren't showing a notification right now or the notification type is changing,
    // definitely do an update.
    if (currentNotification != notificationType) {
      if (currentNotification == NOTIFICATION_NONE) {
        LogUtil.d(
            "StatusBarNotifier.checkForChangeAndSaveData", "showing notification for first time.");
      }
      retval = true;
    }

    savedIcon = icon;
    savedContent = content;
    callState = state;
    this.videoState = videoState;
    savedLargeIcon = largeIcon;
    savedContentTitle = contentTitle;
    this.ringtone = ringtone;
    savedCallAudioState = callAudioState;

    if (retval) {
      LogUtil.d(
          "StatusBarNotifier.checkForChangeAndSaveData", "data changed.  Showing notification");
    }

    return retval;
  }

  /** Returns the main string to use in the notification. */
  @VisibleForTesting
  @Nullable
  String getContentTitle(ContactCacheEntry contactInfo, DialerCall call) {
    if (call.isConferenceCall()) {
      return CallerInfoUtils.getConferenceString(
          context, call.hasProperty(Details.PROPERTY_GENERIC_CONFERENCE));
    }

    String preferredName =
        ContactsComponent.get(context)
            .contactDisplayPreferences()
            .getDisplayName(contactInfo.namePrimary, contactInfo.nameAlternative);
    if (TextUtils.isEmpty(preferredName)) {
      return TextUtils.isEmpty(contactInfo.number)
          ? null
          : BidiFormatter.getInstance()
              .unicodeWrap(contactInfo.number, TextDirectionHeuristics.LTR);
    }
    return preferredName;
  }

  private void addPersonReference(
      Notification.Builder builder, ContactCacheEntry contactInfo, DialerCall call) {
    // Query {@link Contacts#CONTENT_LOOKUP_URI} directly with work lookup key is not allowed.
    // So, do not pass {@link Contacts#CONTENT_LOOKUP_URI} to NotificationManager to avoid
    // NotificationManager using it.
    if (contactInfo.lookupUri != null && contactInfo.userType != ContactsUtils.USER_TYPE_WORK) {
      builder.addPerson(contactInfo.lookupUri.toString());
    } else if (!TextUtils.isEmpty(call.getNumber())) {
      builder.addPerson(Uri.fromParts(PhoneAccount.SCHEME_TEL, call.getNumber(), null).toString());
    }
  }

  /** Gets a large icon from the contact info object to display in the notification. */
  private static Bitmap getLargeIconToDisplay(
      Context context, ContactCacheEntry contactInfo, DialerCall call) {
    Trace.beginSection("StatusBarNotifier.getLargeIconToDisplay");
    Resources resources = context.getResources();
    Bitmap largeIcon = null;
    if (contactInfo.photo != null && (contactInfo.photo instanceof BitmapDrawable)) {
      largeIcon = ((BitmapDrawable) contactInfo.photo).getBitmap();
    }
    if (contactInfo.photo == null) {
      int width = (int) resources.getDimension(android.R.dimen.notification_large_icon_width);
      int height = (int) resources.getDimension(android.R.dimen.notification_large_icon_height);
      @ContactType
      int contactType =
          LetterTileDrawable.getContactTypeFromPrimitives(
              call.isVoiceMailNumber(),
              call.isSpam(),
              contactInfo.isBusiness,
              call.getNumberPresentation(),
              call.isConferenceCall() && !call.hasProperty(Details.PROPERTY_GENERIC_CONFERENCE));
      LetterTileDrawable lettertile = new LetterTileDrawable(resources);

      lettertile.setCanonicalDialerLetterTileDetails(
          contactInfo.namePrimary == null ? contactInfo.number : contactInfo.namePrimary,
          contactInfo.lookupKey,
          LetterTileDrawable.SHAPE_CIRCLE,
          contactType);
      largeIcon = lettertile.getBitmap(width, height);
    }

    if (call.isSpam()) {
      Drawable drawable = resources.getDrawable(R.drawable.blocked_contact, context.getTheme());
      largeIcon = DrawableConverter.drawableToBitmap(drawable);
    }
    Trace.endSection();
    return largeIcon;
  }

  private Bitmap getRoundedIcon(Bitmap bitmap) {
    if (bitmap == null) {
      return null;
    }
    final int height =
        (int) context.getResources().getDimension(android.R.dimen.notification_large_icon_height);
    final int width =
        (int) context.getResources().getDimension(android.R.dimen.notification_large_icon_width);
    return BitmapUtil.getRoundedBitmap(bitmap, width, height);
  }

  /**
   * Returns the appropriate icon res Id to display based on the call for which we want to display
   * information.
   */
  @VisibleForTesting
  public int getIconToDisplay(DialerCall call) {
    // Even if both lines are in use, we only show a single item in
    // the expanded Notifications UI.  It's labeled "Ongoing call"
    // (or "On hold" if there's only one call, and it's on hold.)
    // Also, we don't have room to display caller-id info from two
    // different calls.  So if both lines are in use, display info
    // from the foreground call.  And if there's a ringing call,
    // display that regardless of the state of the other calls.
    if (call.getState() == DialerCallState.ONHOLD) {
      return R.drawable.quantum_ic_phone_paused_vd_theme_24;
    } else if (call.getVideoTech().getSessionModificationState()
            == SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST
        || call.isVideoCall()) {
      return R.drawable.quantum_ic_videocam_vd_white_24;
    } else if (call.hasProperty(PROPERTY_HIGH_DEF_AUDIO)
        && MotorolaUtils.shouldShowHdIconInNotification(context)) {
      // Normally when a call is ongoing the status bar displays an icon of a phone. This is a
      // helpful hint for users so they know how to get back to the call. For Sprint HD calls, we
      // replace this icon with an icon of a phone with a HD badge. This is a carrier requirement.
      return R.drawable.ic_hd_call;
    } else if (call.hasProperty(Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
      return R.drawable.quantum_ic_phone_locked_vd_theme_24;
    }
    // If ReturnToCall is enabled, use the static icon. The animated one will show in the bubble.
    if (ReturnToCallController.isEnabled(context)) {
      return R.drawable.quantum_ic_call_vd_theme_24;
    } else {
      return R.drawable.on_going_call;
    }
  }

  /** Returns the message to use with the notification. */
  private CharSequence getContentString(DialerCall call, @UserType long userType) {
    boolean isIncomingOrWaiting =
        call.getState() == DialerCallState.INCOMING
            || call.getState() == DialerCallState.CALL_WAITING;

    if (isIncomingOrWaiting
        && call.getNumberPresentation() == TelecomManager.PRESENTATION_ALLOWED) {

      if (!TextUtils.isEmpty(call.getChildNumber())) {
        return context.getString(R.string.child_number, call.getChildNumber());
      } else if (!TextUtils.isEmpty(call.getCallSubject()) && call.isCallSubjectSupported()) {
        return call.getCallSubject();
      }
    }

    int resId = R.string.notification_ongoing_call;
    String wifiBrand = context.getString(R.string.notification_call_wifi_brand);
    if (call.hasProperty(Details.PROPERTY_WIFI)) {
      resId = R.string.notification_ongoing_call_wifi_template;
    }

    if (isIncomingOrWaiting) {
      if (call.isSpam()) {
        resId = R.string.notification_incoming_spam_call;
      } else if (shouldShowEnrichedCallNotification(call.getEnrichedCallSession())) {
        resId = getECIncomingCallText(call.getEnrichedCallSession());
      } else if (call.hasProperty(Details.PROPERTY_WIFI)) {
        resId = R.string.notification_incoming_call_wifi_template;
      } else if (call.getAccountHandle() != null && hasMultiplePhoneAccounts(call)) {
        return getMultiSimIncomingText(call);
      } else if (call.isVideoCall()) {
        resId = R.string.notification_incoming_video_call;
      } else {
        resId = R.string.notification_incoming_call;
      }
    } else if (call.getState() == DialerCallState.ONHOLD) {
      resId = R.string.notification_on_hold;
    } else if (call.isVideoCall()) {
      resId =
          call.getVideoTech().isPaused()
              ? R.string.notification_ongoing_paused_video_call
              : R.string.notification_ongoing_video_call;
    } else if (DialerCallState.isDialing(call.getState())) {
      resId = R.string.notification_dialing;
    } else if (call.getVideoTech().getSessionModificationState()
        == SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST) {
      resId = R.string.notification_requesting_video_call;
    }

    // Is the call placed through work connection service.
    boolean isWorkCall = call.hasProperty(PROPERTY_ENTERPRISE_CALL);
    if (userType == ContactsUtils.USER_TYPE_WORK || isWorkCall) {
      resId = getWorkStringFromPersonalString(resId);
      wifiBrand = context.getString(R.string.notification_call_wifi_work_brand);
    }

    if (resId == R.string.notification_incoming_call_wifi_template
        || resId == R.string.notification_ongoing_call_wifi_template) {
      // TODO(a bug): Potentially apply this template logic everywhere.
      return context.getString(resId, wifiBrand);
    }

    return context.getString(resId);
  }

  private boolean shouldShowEnrichedCallNotification(Session session) {
    if (session == null) {
      return false;
    }
    return session.getMultimediaData().hasData() || session.getMultimediaData().isImportant();
  }

  private int getECIncomingCallText(Session session) {
    int resId;
    MultimediaData data = session.getMultimediaData();
    boolean hasImage = data.hasImageData();
    boolean hasSubject = !TextUtils.isEmpty(data.getText());
    boolean hasMap = data.getLocation() != null;
    if (data.isImportant()) {
      if (hasMap) {
        if (hasImage) {
          if (hasSubject) {
            resId = R.string.important_notification_incoming_call_with_photo_message_location;
          } else {
            resId = R.string.important_notification_incoming_call_with_photo_location;
          }
        } else if (hasSubject) {
          resId = R.string.important_notification_incoming_call_with_message_location;
        } else {
          resId = R.string.important_notification_incoming_call_with_location;
        }
      } else if (hasImage) {
        if (hasSubject) {
          resId = R.string.important_notification_incoming_call_with_photo_message;
        } else {
          resId = R.string.important_notification_incoming_call_with_photo;
        }
      } else if (hasSubject) {
        resId = R.string.important_notification_incoming_call_with_message;
      } else {
        resId = R.string.important_notification_incoming_call;
      }
      if (context.getString(resId).length() > 50) {
        resId = R.string.important_notification_incoming_call_attachments;
      }
    } else {
      if (hasMap) {
        if (hasImage) {
          if (hasSubject) {
            resId = R.string.notification_incoming_call_with_photo_message_location;
          } else {
            resId = R.string.notification_incoming_call_with_photo_location;
          }
        } else if (hasSubject) {
          resId = R.string.notification_incoming_call_with_message_location;
        } else {
          resId = R.string.notification_incoming_call_with_location;
        }
      } else if (hasImage) {
        if (hasSubject) {
          resId = R.string.notification_incoming_call_with_photo_message;
        } else {
          resId = R.string.notification_incoming_call_with_photo;
        }
      } else {
        resId = R.string.notification_incoming_call_with_message;
      }
    }
    if (context.getString(resId).length() > 50) {
      resId = R.string.notification_incoming_call_attachments;
    }
    return resId;
  }

  private CharSequence getMultiSimIncomingText(DialerCall call) {
    PhoneAccount phoneAccount =
        context.getSystemService(TelecomManager.class).getPhoneAccount(call.getAccountHandle());
    if (phoneAccount == null) {
      return context.getString(R.string.notification_incoming_call);
    }
    SpannableString string =
        new SpannableString(
            context.getString(
                R.string.notification_incoming_call_mutli_sim, phoneAccount.getLabel()));
    int accountStart = string.toString().lastIndexOf(phoneAccount.getLabel().toString());
    int accountEnd = accountStart + phoneAccount.getLabel().length();

    string.setSpan(
        new ForegroundColorSpan(phoneAccount.getHighlightColor()),
        accountStart,
        accountEnd,
        Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
    return string;
  }

  /** Gets the most relevant call to display in the notification. */
  private DialerCall getCallToShow(CallList callList) {
    if (callList == null) {
      return null;
    }
    DialerCall call = callList.getIncomingCall();
    if (call == null) {
      call = callList.getOutgoingCall();
    }
    if (call == null) {
      call = callList.getVideoUpgradeRequestCall();
    }
    if (call == null) {
      call = callList.getActiveOrBackgroundCall();
    }
    return call;
  }

  private Spannable getActionText(@StringRes int stringRes, @ColorRes int colorRes) {
    Spannable spannable = new SpannableString(context.getText(stringRes));
    if (VERSION.SDK_INT >= VERSION_CODES.N_MR1) {
      // This will only work for cases where the Notification.Builder has a fullscreen intent set
      // Notification.Builder that does not have a full screen intent will take the color of the
      // app and the following leads to a no-op.
      spannable.setSpan(
          new ForegroundColorSpan(context.getColor(colorRes)), 0, spannable.length(), 0);
    }
    return spannable;
  }

  private void addAnswerAction(Notification.Builder builder) {
    LogUtil.d(
        "StatusBarNotifier.addAnswerAction",
        "will show \"answer\" action in the incoming call Notification");
    PendingIntent answerVoicePendingIntent =
        createNotificationPendingIntent(context, ACTION_ANSWER_VOICE_INCOMING_CALL);
    builder.addAction(
        new Notification.Action.Builder(
                Icon.createWithResource(context, R.drawable.quantum_ic_call_white_24),
                getActionText(
                    R.string.notification_action_answer, R.color.notification_action_accept),
                answerVoicePendingIntent)
            .build());
  }

  private void addSpeakeasyAnswerAction(Notification.Builder builder, DialerCall call) {
    if (!call.isSpeakEasyEligible()) {
      return;
    }

    if (!ConfigProviderComponent.get(context)
        .getConfigProvider()
        .getBoolean("enable_speakeasy_notification_button", false)) {
      return;
    }

    if (!SpeakEasyComponent.get(context).speakEasyCallManager().isAvailable(context)) {
      return;
    }

    Optional<Integer> buttonText = SpeakEasyComponent.get(context).speakEasyTextResource();
    if (!buttonText.isPresent()) {
      return;
    }

    LogUtil.d("StatusBarNotifier.addSpeakeasyAnswerAction", "showing button");
    PendingIntent answerVoicePendingIntent =
        createNotificationPendingIntent(context, ACTION_ANSWER_SPEAKEASY_CALL);

    Spannable spannable = new SpannableString(context.getText(buttonText.get()));
    // TODO(erfanian): Migrate these color values to somewhere more permanent in subsequent
    // implementation.
    spannable.setSpan(
        new ForegroundColorSpan(
            context.getColor(R.color.DO_NOT_USE_OR_I_WILL_BREAK_YOU_text_span_tertiary_button)),
        0,
        spannable.length(),
        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

    builder.addAction(
        new Notification.Action.Builder(
                Icon.createWithResource(context, R.drawable.quantum_ic_call_white_24),
                spannable,
                answerVoicePendingIntent)
            .build());
  }

  private void addDismissAction(Notification.Builder builder) {
    LogUtil.d(
        "StatusBarNotifier.addDismissAction",
        "will show \"decline\" action in the incoming call Notification");
    PendingIntent declinePendingIntent =
        createNotificationPendingIntent(context, ACTION_DECLINE_INCOMING_CALL);
    builder.addAction(
        new Notification.Action.Builder(
                Icon.createWithResource(context, R.drawable.quantum_ic_close_white_24),
                getActionText(
                    R.string.notification_action_dismiss, R.color.notification_action_dismiss),
                declinePendingIntent)
            .build());
  }

  private void addHangupAction(Notification.Builder builder) {
    LogUtil.d(
        "StatusBarNotifier.addHangupAction",
        "will show \"hang-up\" action in the ongoing active call Notification");
    PendingIntent hangupPendingIntent =
        createNotificationPendingIntent(context, ACTION_HANG_UP_ONGOING_CALL);
    builder.addAction(
        new Notification.Action.Builder(
                Icon.createWithResource(context, R.drawable.quantum_ic_call_end_white_24),
                context.getText(R.string.notification_action_end_call),
                hangupPendingIntent)
            .build());
  }

  private void addSpeakerAction(Notification.Builder builder, CallAudioState callAudioState) {
    if ((callAudioState.getSupportedRouteMask() & CallAudioState.ROUTE_BLUETOOTH)
        == CallAudioState.ROUTE_BLUETOOTH) {
      // Don't add speaker button if bluetooth is connected
      return;
    }
    if (callAudioState.getRoute() == CallAudioState.ROUTE_SPEAKER) {
      addSpeakerOffAction(builder);
    } else if ((callAudioState.getRoute() & CallAudioState.ROUTE_WIRED_OR_EARPIECE) != 0) {
      addSpeakerOnAction(builder);
    }
  }

  private void addSpeakerOnAction(Notification.Builder builder) {
    LogUtil.d(
        "StatusBarNotifier.addSpeakerOnAction",
        "will show \"Speaker on\" action in the ongoing active call Notification");
    PendingIntent speakerOnPendingIntent =
        createNotificationPendingIntent(context, ACTION_TURN_ON_SPEAKER);
    builder.addAction(
        new Notification.Action.Builder(
                Icon.createWithResource(context, R.drawable.quantum_ic_volume_up_vd_theme_24),
                context.getText(R.string.notification_action_speaker_on),
                speakerOnPendingIntent)
            .build());
  }

  private void addSpeakerOffAction(Notification.Builder builder) {
    LogUtil.d(
        "StatusBarNotifier.addSpeakerOffAction",
        "will show \"Speaker off\" action in the ongoing active call Notification");
    PendingIntent speakerOffPendingIntent =
        createNotificationPendingIntent(context, ACTION_TURN_OFF_SPEAKER);
    builder.addAction(
        new Notification.Action.Builder(
                Icon.createWithResource(context, R.drawable.quantum_ic_phone_in_talk_vd_theme_24),
                context.getText(R.string.notification_action_speaker_off),
                speakerOffPendingIntent)
            .build());
  }

  private void addVideoCallAction(Notification.Builder builder) {
    LogUtil.i(
        "StatusBarNotifier.addVideoCallAction",
        "will show \"video\" action in the incoming call Notification");
    PendingIntent answerVideoPendingIntent =
        createNotificationPendingIntent(context, ACTION_ANSWER_VIDEO_INCOMING_CALL);
    builder.addAction(
        new Notification.Action.Builder(
                Icon.createWithResource(context, R.drawable.quantum_ic_videocam_vd_white_24),
                getActionText(
                    R.string.notification_action_answer_video,
                    R.color.notification_action_answer_video),
                answerVideoPendingIntent)
            .build());
  }

  private void addAcceptUpgradeRequestAction(Notification.Builder builder) {
    LogUtil.i(
        "StatusBarNotifier.addAcceptUpgradeRequestAction",
        "will show \"accept upgrade\" action in the incoming call Notification");
    PendingIntent acceptVideoPendingIntent =
        createNotificationPendingIntent(context, ACTION_ACCEPT_VIDEO_UPGRADE_REQUEST);
    builder.addAction(
        new Notification.Action.Builder(
                Icon.createWithResource(context, R.drawable.quantum_ic_videocam_vd_white_24),
                getActionText(
                    R.string.notification_action_accept, R.color.notification_action_accept),
                acceptVideoPendingIntent)
            .build());
  }

  private void addDismissUpgradeRequestAction(Notification.Builder builder) {
    LogUtil.i(
        "StatusBarNotifier.addDismissUpgradeRequestAction",
        "will show \"dismiss upgrade\" action in the incoming call Notification");
    PendingIntent declineVideoPendingIntent =
        createNotificationPendingIntent(context, ACTION_DECLINE_VIDEO_UPGRADE_REQUEST);
    builder.addAction(
        new Notification.Action.Builder(
                Icon.createWithResource(context, R.drawable.quantum_ic_videocam_vd_white_24),
                getActionText(
                    R.string.notification_action_dismiss, R.color.notification_action_dismiss),
                declineVideoPendingIntent)
            .build());
  }

  /** Adds fullscreen intent to the builder. */
  private void configureFullScreenIntent(Notification.Builder builder, PendingIntent intent) {
    // Ok, we actually want to launch the incoming call
    // UI at this point (in addition to simply posting a notification
    // to the status bar).  Setting fullScreenIntent will cause
    // the InCallScreen to be launched immediately *unless* the
    // current foreground activity is marked as "immersive".
    LogUtil.d("StatusBarNotifier.configureFullScreenIntent", "setting fullScreenIntent: " + intent);
    builder.setFullScreenIntent(intent, true);
  }

  private Notification.Builder getNotificationBuilder() {
    final Notification.Builder builder = new Notification.Builder(context);
    builder.setOngoing(true);
    builder.setOnlyAlertOnce(true);
    // This will be ignored on O+ and handled by the channel
    // noinspection deprecation
    builder.setPriority(Notification.PRIORITY_HIGH);

    return builder;
  }

  private PendingIntent createLaunchPendingIntent(boolean isFullScreen) {
    Intent intent =
        InCallActivity.getIntent(
            context, false /* showDialpad */, false /* newOutgoingCall */, isFullScreen);

    int requestCode = InCallActivity.PendingIntentRequestCodes.NON_FULL_SCREEN;
    if (isFullScreen) {
      // Use a unique request code so that the pending intent isn't clobbered by the
      // non-full screen pending intent.
      requestCode = InCallActivity.PendingIntentRequestCodes.FULL_SCREEN;
    }

    // PendingIntent that can be used to launch the InCallActivity.  The
    // system fires off this intent if the user pulls down the windowshade
    // and clicks the notification's expanded view.  It's also used to
    // launch the InCallActivity immediately when when there's an incoming
    // call (see the "fullScreenIntent" field below).
    return PendingIntent.getActivity(context, requestCode, intent, 0);
  }

  private void setStatusBarCallListener(StatusBarCallListener listener) {
    if (statusBarCallListener != null) {
      statusBarCallListener.cleanup();
    }
    statusBarCallListener = listener;
  }

  private boolean hasMultiplePhoneAccounts(DialerCall call) {
    if (call.getCallCapableAccounts() == null) {
      return false;
    }
    return call.getCallCapableAccounts().size() > 1;
  }

  @Override
  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
  public void onContactInfoComplete(String callId, ContactCacheEntry entry) {
    DialerCall call = CallList.getInstance().getCallById(callId);
    if (call != null) {
      call.getLogState().contactLookupResult = entry.contactLookupResult;
      buildAndSendNotification(CallList.getInstance(), call, entry);
    }
  }

  @Override
  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
  public void onImageLoadComplete(String callId, ContactCacheEntry entry) {
    DialerCall call = CallList.getInstance().getCallById(callId);
    if (call != null) {
      buildAndSendNotification(CallList.getInstance(), call, entry);
    }
  }

  private class StatusBarCallListener implements DialerCallListener {

    private DialerCall dialerCall;

    StatusBarCallListener(DialerCall dialerCall) {
      this.dialerCall = dialerCall;
      this.dialerCall.addListener(this);
    }

    void cleanup() {
      dialerCall.removeListener(this);
    }

    @Override
    public void onDialerCallDisconnect() {}

    @Override
    public void onDialerCallUpdate() {
      if (CallList.getInstance().getIncomingCall() == null) {
        dialerRingtoneManager.stopCallWaitingTone();
      }
    }

    @Override
    public void onDialerCallChildNumberChange() {}

    @Override
    public void onDialerCallLastForwardedNumberChange() {}

    @Override
    public void onDialerCallUpgradeToVideo() {}

    @Override
    public void onWiFiToLteHandover() {}

    @Override
    public void onHandoverToWifiFailure() {}

    @Override
    public void onInternationalCallOnWifi() {}

    @Override
    public void onEnrichedCallSessionUpdate() {}

    /**
     * Responds to changes in the session modification state for the call by dismissing the status
     * bar notification as required.
     */
    @Override
    public void onDialerCallSessionModificationStateChange() {
      if (dialerCall.getVideoTech().getSessionModificationState()
          == SessionModificationState.NO_REQUEST) {
        cleanup();
        updateNotification();
      }
    }
  }
}
