/*
 * Copyright (C) 2014 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 android.telecomm;

import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import com.android.internal.telecomm.ITelecommService;

import java.util.ArrayList;
import java.util.List;

/**
 * Provides access to Telecomm-related functionality.
 * TODO: Move this all into PhoneManager.
 */
public class TelecommManager {

    /**
     * Activity action: Starts the UI for handing an incoming call. This intent starts the in-call
     * UI by notifying the Telecomm system that an incoming call exists for a specific call service
     * (see {@link android.telecomm.ConnectionService}). Telecomm reads the Intent extras to find
     * and bind to the appropriate {@link android.telecomm.ConnectionService} which Telecomm will
     * ultimately use to control and get information about the call.
     * <p>
     * Input: get*Extra field {@link #EXTRA_PHONE_ACCOUNT_HANDLE} contains the component name of the
     * {@link android.telecomm.ConnectionService} that Telecomm should bind to. Telecomm will then
     * ask the connection service for more information about the call prior to showing any UI.
     *
     * @hide
     */
    public static final String ACTION_INCOMING_CALL = "android.intent.action.INCOMING_CALL";

    /**
     * The {@link android.content.Intent} action used to configure a
     * {@link android.telecomm.ConnectionService}.
     */
    public static final String ACTION_CONNECTION_SERVICE_CONFIGURE =
            "android.intent.action.CONNECTION_SERVICE_CONFIGURE";

    /**
     * The {@link android.content.Intent} action used to show the call settings page.
     */
    public static final String ACTION_SHOW_CALL_SETTINGS =
            "android.telecomm.intent.action.SHOW_CALL_SETTINGS";

    /**
     * Optional extra for {@link android.content.Intent#ACTION_CALL} containing a boolean that
     * determines whether the speakerphone should be automatically turned on for an outgoing call.
     */
    public static final String EXTRA_START_CALL_WITH_SPEAKERPHONE =
            "android.intent.extra.START_CALL_WITH_SPEAKERPHONE";

    /**
     * Optional extra for {@link android.content.Intent#ACTION_CALL} containing an integer that
     * determines the desired video state for an outgoing call.
     * Valid options:
     * {@link VideoProfile.VideoState#AUDIO_ONLY},
     * {@link VideoProfile.VideoState#BIDIRECTIONAL},
     * {@link VideoProfile.VideoState#RX_ENABLED},
     * {@link VideoProfile.VideoState#TX_ENABLED}.
     * @hide
     */
    public static final String EXTRA_START_CALL_WITH_VIDEO_STATE =
            "android.intent.extra.START_CALL_WITH_VIDEO_STATE";

    /**
     * The extra used with an {@link android.content.Intent#ACTION_CALL} and
     * {@link android.content.Intent#ACTION_DIAL} {@code Intent} to specify a
     * {@link PhoneAccountHandle} to use when making the call.
     * <p class="note">
     * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
     */
    public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
            "android.intent.extra.PHONE_ACCOUNT_HANDLE";

    /**
     * Optional extra for {@link #ACTION_INCOMING_CALL} containing a {@link Bundle} which contains
     * metadata about the call. This {@link Bundle} will be returned to the
     * {@link ConnectionService}.
     *
     * @hide
     */
    public static final String EXTRA_INCOMING_CALL_EXTRAS =
            "android.intent.extra.INCOMING_CALL_EXTRAS";

    /**
     * Optional extra for {@link android.content.Intent#ACTION_CALL} and
     * {@link android.content.Intent#ACTION_DIAL} {@code Intent} containing a {@link Bundle}
     * which contains metadata about the call. This {@link Bundle} will be saved into
     * {@code Call.Details}.
     *
     * @hide
     */
    public static final String EXTRA_OUTGOING_CALL_EXTRAS =
            "android.intent.extra.OUTGOING_CALL_EXTRAS";

    /**
     * Optional extra for {@link android.telephony.TelephonyManager#ACTION_PHONE_STATE_CHANGED}
     * containing the disconnect code.
     */
    public static final String EXTRA_CALL_DISCONNECT_CAUSE =
            "android.telecomm.extra.CALL_DISCONNECT_CAUSE";

    /**
     * Optional extra for {@link android.telephony.TelephonyManager#ACTION_PHONE_STATE_CHANGED}
     * containing the disconnect message.
     */
    public static final String EXTRA_CALL_DISCONNECT_MESSAGE =
            "android.telecomm.extra.CALL_DISCONNECT_MESSAGE";

    /**
     * Optional extra for {@link android.telephony.TelephonyManager#ACTION_PHONE_STATE_CHANGED}
     * containing the component name of the associated connection service.
     */
    public static final String EXTRA_CONNECTION_SERVICE =
            "android.telecomm.extra.CONNECTION_SERVICE";

    /**
     * The number which the party on the other side of the line will see (and use to return the
     * call).
     * <p>
     * {@link ConnectionService}s which interact with {@link RemoteConnection}s should only populate
     * this if the {@link android.telephony.TelephonyManager#getLine1Number()} value, as that is the
     * user's expected caller ID.
     */
    public static final String EXTRA_CALL_BACK_NUMBER = "android.telecomm.extra.CALL_BACK_NUMBER";

    /**
     * The dual tone multi-frequency signaling character sent to indicate the dialing system should
     * pause for a predefined period.
     */
    public static final char DTMF_CHARACTER_PAUSE = ',';

    /**
     * The dual-tone multi-frequency signaling character sent to indicate the dialing system should
     * wait for user confirmation before proceeding.
     */
    public static final char DTMF_CHARACTER_WAIT = ';';

    /**
     * TTY (teletypewriter) mode is off.
     *
     * @hide
     */
    public static final int TTY_MODE_OFF = 0;

    /**
     * TTY (teletypewriter) mode is on. The speaker is off and the microphone is muted. The user
     * will communicate with the remote party by sending and receiving text messages.
     *
     * @hide
     */
    public static final int TTY_MODE_FULL = 1;

    /**
     * TTY (teletypewriter) mode is in hearing carryover mode (HCO). The microphone is muted but the
     * speaker is on. The user will communicate with the remote party by sending text messages and
     * hearing an audible reply.
     *
     * @hide
     */
    public static final int TTY_MODE_HCO = 2;

    /**
     * TTY (teletypewriter) mode is in voice carryover mode (VCO). The speaker is off but the
     * microphone is still on. User will communicate with the remote party by speaking and receiving
     * text message replies.
     *
     * @hide
     */
    public static final int TTY_MODE_VCO = 3;

    /**
     * Broadcast intent action indicating that the current TTY mode has changed. An intent extra
     * provides this state as an int.
     *
     * @see #EXTRA_CURRENT_TTY_MODE
     * @hide
     */
    public static final String ACTION_CURRENT_TTY_MODE_CHANGED =
            "android.telecomm.intent.action.CURRENT_TTY_MODE_CHANGED";

    /**
     * The lookup key for an int that indicates the current TTY mode.
     * Valid modes are:
     * - {@link #TTY_MODE_OFF}
     * - {@link #TTY_MODE_FULL}
     * - {@link #TTY_MODE_HCO}
     * - {@link #TTY_MODE_VCO}
     *
     * @hide
     */
    public static final String EXTRA_CURRENT_TTY_MODE =
            "android.telecomm.intent.extra.CURRENT_TTY_MODE";

    /**
     * Broadcast intent action indicating that the TTY preferred operating mode has changed. An
     * intent extra provides the new mode as an int.
     *
     * @see #EXTRA_TTY_PREFERRED_MODE
     * @hide
     */
    public static final String ACTION_TTY_PREFERRED_MODE_CHANGED =
            "android.telecomm.intent.action.TTY_PREFERRED_MODE_CHANGED";

    /**
     * The lookup key for an int that indicates preferred TTY mode. Valid modes are: -
     * {@link #TTY_MODE_OFF} - {@link #TTY_MODE_FULL} - {@link #TTY_MODE_HCO} -
     * {@link #TTY_MODE_VCO}
     *
     * @hide
     */
    public static final String EXTRA_TTY_PREFERRED_MODE =
            "android.telecomm.intent.extra.TTY_PREFERRED";

    private static final String TAG = "TelecommManager";

    private static final String TELECOMM_SERVICE_NAME = "telecomm";

    private final Context mContext;

    /**
     * @hide
     */
    public static TelecommManager from(Context context) {
        return (TelecommManager) context.getSystemService(Context.TELECOMM_SERVICE);
    }

    /**
     * @hide
     */
    public TelecommManager(Context context) {
        Context appContext = context.getApplicationContext();
        if (appContext != null) {
            mContext = appContext;
        } else {
            mContext = context;
        }
    }

    /**
     * Return the {@link PhoneAccount} which is the user-chosen default for making outgoing phone
     * calls. This {@code PhoneAccount} will always be a member of the list which is returned from
     * calling {@link #getEnabledPhoneAccounts()}.
     * <p>
     * Apps must be prepared for this method to return {@code null}, indicating that there currently
     * exists no user-chosen default {@code PhoneAccount}. In this case, apps wishing to initiate a
     * phone call must either create their {@link android.content .Intent#ACTION_CALL} or
     * {@link android.content.Intent#ACTION_DIAL} {@code Intent} with no
     * {@link TelecommManager#EXTRA_PHONE_ACCOUNT_HANDLE}, or present the user with an affordance to
     * select one of the elements of {@link #getEnabledPhoneAccounts()}.
     * <p>
     * An {@link android.content.Intent#ACTION_CALL} or {@link android.content.Intent#ACTION_DIAL}
     * {@code Intent} with no {@link TelecommManager#EXTRA_PHONE_ACCOUNT_HANDLE} is valid, and
     * subsequent steps in the phone call flow are responsible for presenting the user with an
     * affordance, if necessary, to choose a {@code PhoneAccount}.
     */
    public PhoneAccountHandle getDefaultOutgoingPhoneAccount() {
        try {
            if (isServiceConnected()) {
                return getTelecommService().getDefaultOutgoingPhoneAccount();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecommService#getDefaultOutgoingPhoneAccount", e);
        }
        return null;
    }

    /**
     * Return a list of {@link PhoneAccountHandle}s which can be used to make and receive phone
     * calls.
     *
     * @see #EXTRA_PHONE_ACCOUNT_HANDLE
     * @return A list of {@code PhoneAccountHandle} objects.
     */
    public List<PhoneAccountHandle> getEnabledPhoneAccounts() {
        try {
            if (isServiceConnected()) {
                return getTelecommService().getOutgoingPhoneAccounts();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecommService#getOutgoingPhoneAccounts", e);
        }
        return new ArrayList<>();
    }

    /**
     * Determine whether the device has more than one account registered and enabled.
     *
     * @return {@code true} if the device has more than one account registered and enabled and
     * {@code false} otherwise.
     */
    public boolean hasMultipleEnabledAccounts() {
        return getEnabledPhoneAccounts().size() > 1;
    }

    /**
     * Return the {@link PhoneAccount} for a specified {@link PhoneAccountHandle}. Object includes
     * resources which can be used in a user interface.
     *
     * @param account The {@link PhoneAccountHandle}.
     * @return The {@link PhoneAccount} object.
     */
    public PhoneAccount getPhoneAccount(PhoneAccountHandle account) {
        try {
            if (isServiceConnected()) {
                return getTelecommService().getPhoneAccount(account);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecommService#getPhoneAccount", e);
        }
        return null;
    }

    /**
     * Register a {@link PhoneAccount} for use by the system.
     *
     * @param account The complete {@link PhoneAccount}.
     */
    public void registerPhoneAccount(PhoneAccount account) {
        try {
            if (isServiceConnected()) {
                getTelecommService().registerPhoneAccount(account);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecommService#registerPhoneAccount", e);
        }
    }

    /**
     * Remove a {@link PhoneAccount} registration from the system.
     *
     * @param accountHandle A {@link PhoneAccountHandle} for the {@link PhoneAccount} to unregister.
     */
    public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
        try {
            if (isServiceConnected()) {
                getTelecommService().unregisterPhoneAccount(accountHandle);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecommService#unregisterPhoneAccount", e);
        }
    }

    /**
     * Remove all Accounts for a given package from the system.
     *
     * @param packageName A package name that may have registered Accounts.
     */
    @SystemApi
    public void clearAccounts(String packageName) {
        try {
            if (isServiceConnected()) {
                getTelecommService().clearAccounts(packageName);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecommService#clearAccounts", e);
        }
    }

    /**
     * @hide
     */
    @SystemApi
    public ComponentName getDefaultPhoneApp() {
        try {
            if (isServiceConnected()) {
                return getTelecommService().getDefaultPhoneApp();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException attempting to get the default phone app.", e);
        }
        return null;
    }

    /**
     * Returns whether there is an ongoing phone call (can be in dialing, ringing, active or holding
     * states).
     * <p>
     * Requires permission: {@link android.Manifest.permission#READ_PHONE_STATE}
     * </p>
     */
    @SystemApi
    public boolean isInCall() {
        try {
            if (isServiceConnected()) {
                return getTelecommService().isInCall();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException attempting to get default phone app.", e);
        }
        return false;
    }

    /**
     * Returns whether there currently exists is a ringing incoming-call.
     *
     * @hide
     */
    @SystemApi
    public boolean isRinging() {
        try {
            if (isServiceConnected()) {
                return getTelecommService().isRinging();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException attempting to get ringing state of phone app.", e);
        }
        return false;
    }

    /**
     * Ends an ongoing call.
     * TODO: L-release - need to convert all invocations of ITelecommService#endCall to use this
     * method (clockwork & gearhead).
     * @hide
     */
    @SystemApi
    public boolean endCall() {
        try {
            if (isServiceConnected()) {
                return getTelecommService().endCall();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecommService#endCall", e);
        }
        return false;
    }

    /**
     * If there is a ringing incoming call, this method accepts the call on behalf of the user.
     * TODO: L-release - need to convert all invocation of ITelecommService#answerRingingCall to use
     * this method (clockwork & gearhead).
     *
     * @hide
     */
    @SystemApi
    public void acceptRingingCall() {
        try {
            if (isServiceConnected()) {
                getTelecommService().acceptRingingCall();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecommService#acceptRingingCall", e);
        }
    }

    /**
     * Silences the ringer if a ringing call exists.
     *
     * @hide
     */
    @SystemApi
    public void silenceRinger() {
        try {
            if (isServiceConnected()) {
                getTelecommService().silenceRinger();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecommService#silenceRinger", e);
        }
    }

    /**
     * Returns whether TTY is supported on this device.
     *
     * @hide
     */
    @SystemApi
    public boolean isTtySupported() {
        try {
            if (isServiceConnected()) {
                return getTelecommService().isTtySupported();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException attempting to get TTY supported state.", e);
        }
        return false;
    }

    /**
     * Returns the current TTY mode of the device. For TTY to be on the user must enable it in
     * settings and have a wired headset plugged in.
     * Valid modes are:
     * - {@link TelecommManager#TTY_MODE_OFF}
     * - {@link TelecommManager#TTY_MODE_FULL}
     * - {@link TelecommManager#TTY_MODE_HCO}
     * - {@link TelecommManager#TTY_MODE_VCO}
     * @hide
     */
    public int getCurrentTtyMode() {
        try {
            if (isServiceConnected()) {
                return getTelecommService().getCurrentTtyMode();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException attempting to get the current TTY mode.", e);
        }
        return TTY_MODE_OFF;
    }

    /**
     * Registers a new incoming call. A {@link ConnectionService} should invoke this method when it
     * has an incoming call. The specified {@link PhoneAccountHandle} must have been registered
     * with {@link #registerPhoneAccount} and subsequently enabled by the user within the phone's
     * settings. Once invoked, this method will cause the system to bind to the
     * {@link ConnectionService} associated with the {@link PhoneAccountHandle} and request
     * additional information about the call (See
     * {@link ConnectionService#onCreateIncomingConnection}) before starting the incoming call UI.
     *
     * @param phoneAccount A {@link PhoneAccountHandle} registered with
     *            {@link #registerPhoneAccount}.
     * @param extras A bundle that will be passed through to
     *            {@link ConnectionService#onCreateIncomingConnection}.
     */
    public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) {
        try {
            if (isServiceConnected()) {
                getTelecommService().addNewIncomingCall(
                        phoneAccount, extras == null ? new Bundle() : extras);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException adding a new incoming call: " + phoneAccount, e);
        }
    }

    /**
     * Processes the specified dial string as an MMI code.
     * MMI codes are any sequence of characters entered into the dialpad that contain a "*" or "#".
     * Some of these sequences launch special behavior through handled by Telephony.
     * <p>
     * Requires that the method-caller be set as the system dialer app.
     * </p>
     *
     * @param dialString The digits to dial.
     * @return True if the digits were processed as an MMI code, false otherwise.
     */
    public boolean handleMmi(String dialString) {
        ITelecommService service = getTelecommService();
        if (service != null) {
            try {
                return service.handlePinMmi(dialString);
            } catch (RemoteException e) {
                Log.e(TAG, "Error calling ITelecommService#handlePinMmi", e);
            }
        }
        return false;
    }

    /**
     * Removes the missed-call notification if one is present.
     * <p>
     * Requires that the method-caller be set as the system dialer app.
     * </p>
     */
    public void cancelMissedCallsNotification() {
        ITelecommService service = getTelecommService();
        if (service != null) {
            try {
                service.cancelMissedCallsNotification();
            } catch (RemoteException e) {
                Log.e(TAG, "Error calling ITelecommService#cancelMissedCallsNotification", e);
            }
        }
    }

    /**
     * Brings the in-call screen to the foreground if there is an ongoing call. If there is
     * currently no ongoing call, then this method does nothing.
     * <p>
     * Requires that the method-caller be set as the system dialer app or have the
     * {@link android.Manifest.permission#READ_PHONE_STATE} permission.
     * </p>
     *
     * @param showDialpad Brings up the in-call dialpad as part of showing the in-call screen.
     */
    public void showInCallScreen(boolean showDialpad) {
        ITelecommService service = getTelecommService();
        if (service != null) {
            try {
                service.showInCallScreen(showDialpad);
            } catch (RemoteException e) {
                Log.e(TAG, "Error calling ITelecommService#showCallScreen", e);
            }
        }
    }

    private ITelecommService getTelecommService() {
        return ITelecommService.Stub.asInterface(ServiceManager.getService(TELECOMM_SERVICE_NAME));
    }

    private boolean isServiceConnected() {
        boolean isConnected = getTelecommService() != null;
        if (!isConnected) {
            Log.w(TAG, "Telecomm Service not found.");
        }
        return isConnected;
    }
}
