/*
 * Copyright (C) 2017 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.server.telecom.ui;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telecom.Log;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.ArraySet;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallState;
import com.android.server.telecom.CallsManagerListenerBase;
import com.android.server.telecom.HandoverState;
import com.android.server.telecom.R;
import com.android.server.telecom.TelecomBroadcastIntentProcessor;
import com.android.server.telecom.components.TelecomBroadcastReceiver;

import java.util.Objects;
import java.util.Optional;
import java.util.Set;

/**
 * Manages the display of an incoming call UX when a new ringing self-managed call is added, and
 * there is an ongoing call in another {@link android.telecom.PhoneAccount}.
 */
public class IncomingCallNotifier extends CallsManagerListenerBase {

    public interface IncomingCallNotifierFactory {
        IncomingCallNotifier make(Context context, CallsManagerProxy mCallsManagerProxy);
    }

    /**
     * Eliminates strict dependency between this class and CallsManager.
     */
    public interface CallsManagerProxy {
        boolean hasUnholdableCallsForOtherConnectionService(PhoneAccountHandle phoneAccountHandle);
        int getNumUnholdableCallsForOtherConnectionService(PhoneAccountHandle phoneAccountHandle);
        Call getActiveCall();
    }

    // Notification for incoming calls. This is interruptive and will show up as a HUN.
    @VisibleForTesting
    public static final int NOTIFICATION_INCOMING_CALL = 1;
    @VisibleForTesting
    public static final String NOTIFICATION_TAG = IncomingCallNotifier.class.getSimpleName();
    private final Object mLock = new Object();

    public final Call.ListenerBase mCallListener = new Call.ListenerBase() {
        @Override
        public void onCallerInfoChanged(Call call) {
            if (mIncomingCall != call) {
                return;
            }
            showIncomingCallNotification(mIncomingCall);
        }
    };

    private final Context mContext;
    private final NotificationManager mNotificationManager;
    private final Set<Call> mCalls = new ArraySet<>();
    private CallsManagerProxy mCallsManagerProxy;

    // The current incoming call we are displaying UX for.
    private Call mIncomingCall;

    public IncomingCallNotifier(Context context) {
        mContext = context;
        mNotificationManager =
                (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    }

    public void setCallsManagerProxy(CallsManagerProxy callsManagerProxy) {
        mCallsManagerProxy = callsManagerProxy;
    }

    public Call getIncomingCall() {
        return mIncomingCall;
    }

    @Override
    public void onCallAdded(Call call) {
        synchronized (mLock) {
            if (!mCalls.contains(call)) {
                mCalls.add(call);
            }
        }

        updateIncomingCall();
    }

    @Override
    public void onCallRemoved(Call call) {
        synchronized (mLock) {
            if (mCalls.contains(call)) {
                mCalls.remove(call);
            }
        }
        updateIncomingCall();
    }

    @Override
    public void onCallStateChanged(Call call, int oldState, int newState) {
        updateIncomingCall();
    }

    /**
     * Determines which call is the active ringing call at this time and triggers the display of the
     * UI.
     */
    private void updateIncomingCall() {
        Optional<Call> incomingCallOp;
        synchronized (mLock) {
            incomingCallOp = mCalls.stream()
                    .filter(Objects::nonNull)
                    .filter(call -> call.isSelfManaged() && call.isIncoming() &&
                            call.getState() == CallState.RINGING &&
                            call.getHandoverState() == HandoverState.HANDOVER_NONE)
                    .findFirst();
        }

        Call incomingCall = incomingCallOp.orElse(null);
        if (incomingCall != null && mCallsManagerProxy != null &&
                !mCallsManagerProxy.hasUnholdableCallsForOtherConnectionService(
                        incomingCallOp.get().getTargetPhoneAccount())) {
            // If there is no calls in any other ConnectionService, we can rely on the
            // third-party app to display its own incoming call UI.
            incomingCall = null;
        }

        Log.i(this, "updateIncomingCall: foundIncomingcall = %s", incomingCall);

        boolean hadIncomingCall = mIncomingCall != null;
        boolean hasIncomingCall = incomingCall != null;
        if (incomingCall != mIncomingCall) {
            Call previousIncomingCall = mIncomingCall;
            mIncomingCall = incomingCall;

            if (hasIncomingCall && !hadIncomingCall) {
                mIncomingCall.addListener(mCallListener);
                showIncomingCallNotification(mIncomingCall);
            } else if (hadIncomingCall && !hasIncomingCall) {
                previousIncomingCall.removeListener(mCallListener);
                hideIncomingCallNotification();
            }
        }
    }

    private void showIncomingCallNotification(Call call) {
        Log.i(this, "showIncomingCallNotification showCall = %s", call);

        Notification.Builder builder = getNotificationBuilder(call,
                mCallsManagerProxy.getActiveCall());
        mNotificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_INCOMING_CALL, builder.build());
    }

    private void hideIncomingCallNotification() {
        Log.i(this, "hideIncomingCallNotification");
        mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_INCOMING_CALL);
    }

    private String getNotificationName(Call call) {
        String name = "";
        if (call.getCallerDisplayNamePresentation() == TelecomManager.PRESENTATION_ALLOWED) {
            name = call.getCallerDisplayName();
        }
        if (TextUtils.isEmpty(name)) {
            name = call.getName();
        }

        if (TextUtils.isEmpty(name)) {
            name = call.getPhoneNumber();
        }
        return name;
    }

    private Notification.Builder getNotificationBuilder(Call incomingCall, Call ongoingCall) {
        // Change the notification app name to "Android System" to sufficiently distinguish this
        // from the phone app's name.
        Bundle extras = new Bundle();
        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, mContext.getString(
                com.android.internal.R.string.android_system_label));

        Intent answerIntent = new Intent(
                TelecomBroadcastIntentProcessor.ACTION_ANSWER_FROM_NOTIFICATION, null, mContext,
                TelecomBroadcastReceiver.class);
        Intent rejectIntent = new Intent(
                TelecomBroadcastIntentProcessor.ACTION_REJECT_FROM_NOTIFICATION, null, mContext,
                TelecomBroadcastReceiver.class);

        String nameOrNumber = getNotificationName(incomingCall);
        CharSequence viaApp = incomingCall.getTargetPhoneAccountLabel();
        boolean isIncomingVideo = VideoProfile.isVideo(incomingCall.getVideoState());
        boolean isOngoingVideo = ongoingCall != null ?
                VideoProfile.isVideo(ongoingCall.getVideoState()) : false;
        int numOtherCalls = ongoingCall != null ?
                mCallsManagerProxy.getNumUnholdableCallsForOtherConnectionService(
                        incomingCall.getTargetPhoneAccount()) : 1;

        // Build the "IncomingApp call from John Smith" message.
        CharSequence incomingCallText;
        if (isIncomingVideo) {
            incomingCallText = mContext.getString(R.string.notification_incoming_video_call, viaApp,
                    nameOrNumber);
        } else {
            incomingCallText = mContext.getString(R.string.notification_incoming_call, viaApp,
                    nameOrNumber);
        }

        // Build the "Answering will end your OtherApp call" line.
        CharSequence disconnectText;
        if (ongoingCall != null && ongoingCall.isSelfManaged()) {
            CharSequence ongoingApp = ongoingCall.getTargetPhoneAccountLabel();
            // For an ongoing self-managed call, we use a message like:
            // "Answering will end your OtherApp call".
            if (numOtherCalls > 1) {
                // Multiple ongoing calls in the other app, so don't bother specifing whether it is
                // a video call or audio call.
                disconnectText = mContext.getString(R.string.answering_ends_other_calls,
                        ongoingApp);
            } else if (isOngoingVideo) {
                disconnectText = mContext.getString(R.string.answering_ends_other_video_call,
                        ongoingApp);
            } else {
                disconnectText = mContext.getString(R.string.answering_ends_other_call, ongoingApp);
            }
        } else {
            // For an ongoing managed call, we use a message like:
            // "Answering will end your ongoing call".
            if (numOtherCalls > 1) {
                // Multiple ongoing manage calls, so don't bother specifing whether it is a video
                // call or audio call.
                disconnectText = mContext.getString(R.string.answering_ends_other_managed_calls);
            } else if (isOngoingVideo) {
                disconnectText = mContext.getString(
                        R.string.answering_ends_other_managed_video_call);
            } else {
                disconnectText = mContext.getString(R.string.answering_ends_other_managed_call);
            }
        }

        final Notification.Builder builder = new Notification.Builder(mContext);
        builder.setOngoing(true);
        builder.setExtras(extras);
        builder.setPriority(Notification.PRIORITY_HIGH);
        builder.setCategory(Notification.CATEGORY_CALL);
        builder.setContentTitle(incomingCallText);
        builder.setContentText(disconnectText);
        builder.setSmallIcon(R.drawable.ic_phone);
        builder.setChannelId(NotificationChannelManager.CHANNEL_ID_INCOMING_CALLS);
        // Ensures this is a heads up notification.  A heads-up notification is typically only shown
        // if there is a fullscreen intent.  However since this notification doesn't have that we
        // will use this trick to get it to show as one anyways.
        builder.setVibrate(new long[0]);
        builder.setColor(mContext.getResources().getColor(R.color.theme_color));
        builder.addAction(
                R.anim.on_going_call,
                getActionText(R.string.answer_incoming_call, R.color.notification_action_answer),
                PendingIntent.getBroadcast(mContext, 0, answerIntent,
                        PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE));
        builder.addAction(
                R.drawable.ic_close_dk,
                getActionText(R.string.decline_incoming_call, R.color.notification_action_decline),
                PendingIntent.getBroadcast(mContext, 0, rejectIntent,
                        PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE));
        return builder;
    }

    private CharSequence getActionText(int stringRes, int colorRes) {
        CharSequence string = mContext.getText(stringRes);
        if (string == null) {
            return "";
        }
        Spannable spannable = new SpannableString(string);
        spannable.setSpan(
                    new ForegroundColorSpan(mContext.getColor(colorRes)), 0, spannable.length(), 0);
        return spannable;
    }
}
