/*
 * Copyright (C) 2015 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.dialer.telecom;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothHeadsetClientCall;
import android.bluetooth.BluetoothProfile;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.net.Uri;
import android.os.IBinder;
import android.provider.CallLog;
import android.telecom.Call;
import android.telecom.CallAudioState;
import android.telecom.CallAudioState.CallAudioRoute;
import android.telecom.DisconnectCause;
import android.telecom.GatewayInfo;
import android.telecom.InCallService;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;

import com.android.car.dialer.CallListener;
import com.android.car.dialer.R;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * The entry point for all interactions between UI and telecom.
 */
public class UiCallManager {
    private static String TAG = "Em.TelecomMgr";

    private static final String HFP_CLIENT_CONNECTION_SERVICE_CLASS_NAME
            = "com.android.bluetooth.hfpclient.connserv.HfpClientConnectionService";
    // Rate limit how often you can place outgoing calls.
    private static final long MIN_TIME_BETWEEN_CALLS_MS = 3000;
    private static final List<Integer> sCallStateRank = new ArrayList<>();
    private static UiCallManager sUiCallManager;

    // Used to assign id's to UiCall objects as they're created.
    private static int nextCarPhoneCallId = 0;

    static {
        // States should be added from lowest rank to highest
        sCallStateRank.add(Call.STATE_DISCONNECTED);
        sCallStateRank.add(Call.STATE_DISCONNECTING);
        sCallStateRank.add(Call.STATE_NEW);
        sCallStateRank.add(Call.STATE_CONNECTING);
        sCallStateRank.add(Call.STATE_SELECT_PHONE_ACCOUNT);
        sCallStateRank.add(Call.STATE_HOLDING);
        sCallStateRank.add(Call.STATE_ACTIVE);
        sCallStateRank.add(Call.STATE_DIALING);
        sCallStateRank.add(Call.STATE_RINGING);
    }

    private Context mContext;
    private TelephonyManager mTelephonyManager;
    private long mLastPlacedCallTimeMs;

    private TelecomManager mTelecomManager;
    private InCallServiceImpl mInCallService;
    private BluetoothHeadsetClient mBluetoothHeadsetClient;
    private final Map<UiCall, Call> mCallMapping = new HashMap<>();
    private final List<CallListener> mCallListeners = new CopyOnWriteArrayList<>();

    /**
     * Initialized a globally accessible {@link UiCallManager} which can be retrieved by
     * {@link #get}. If this function is called a second time before calling {@link #tearDown()},
     * an exception will be thrown.
     *
     * @param applicationContext Application context.
     */
    public static UiCallManager init(Context applicationContext) {
        if (sUiCallManager == null) {
            sUiCallManager = new UiCallManager(applicationContext);
        } else {
            throw new IllegalStateException("UiCallManager has been initialized.");
        }
        return sUiCallManager;
    }

    /**
     * Gets the global {@link UiCallManager} instance. Make sure
     * {@link #init(Context)} is called before calling this method.
     */
    public static UiCallManager get() {
        if (sUiCallManager == null) {
            throw new IllegalStateException(
                    "Call UiCallManager.init(Context) before calling this function");
        }
        return sUiCallManager;
    }

    private UiCallManager(Context context) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "SetUp");
        }

        mContext = context;
        mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);

        mTelecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
        Intent intent = new Intent(context, InCallServiceImpl.class);
        intent.setAction(InCallServiceImpl.ACTION_LOCAL_BIND);
        context.bindService(intent, mInCallServiceConnection, Context.BIND_AUTO_CREATE);

        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (adapter != null) {
            adapter.getProfileProxy(mContext, new BluetoothProfile.ServiceListener() {
                @Override
                public void onServiceConnected(int profile, BluetoothProfile proxy) {
                    if (profile == BluetoothProfile.HEADSET_CLIENT) {
                        mBluetoothHeadsetClient = (BluetoothHeadsetClient) proxy;
                    }
                }

                @Override
                public void onServiceDisconnected(int profile) {
                }
            }, BluetoothProfile.HEADSET_CLIENT);
        }
    }

    private final ServiceConnection mInCallServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onServiceConnected: " + name + ", service: " + binder);
            }
            mInCallService = ((InCallServiceImpl.LocalBinder) binder).getService();
            mInCallService.registerCallback(mInCallServiceCallback);

            // The InCallServiceImpl could be bound when we already have some active calls, let's
            // notify UI about these calls.
            for (Call telecomCall : mInCallService.getCalls()) {
                UiCall uiCall = doTelecomCallAdded(telecomCall);
                onStateChanged(uiCall, uiCall.getState());
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onServiceDisconnected: " + name);
            }
            mInCallService.unregisterCallback(mInCallServiceCallback);
        }

        private InCallServiceImpl.Callback mInCallServiceCallback =
                new InCallServiceImpl.Callback() {
                    @Override
                    public void onTelecomCallAdded(Call telecomCall) {
                        doTelecomCallAdded(telecomCall);
                    }

                    @Override
                    public void onTelecomCallRemoved(Call telecomCall) {
                        doTelecomCallRemoved(telecomCall);
                    }

                    @Override
                    public void onCallAudioStateChanged(CallAudioState audioState) {
                        doCallAudioStateChanged(audioState);
                    }
                };
    };

    /**
     * Tears down the {@link UiCallManager}. Calling this function will null out the global
     * accessible {@link UiCallManager} instance. Remember to re-initialize the
     * {@link UiCallManager}.
     */
    public void tearDown() {
        if (mInCallService != null) {
            mContext.unbindService(mInCallServiceConnection);
            mInCallService = null;
        }
        mCallMapping.clear();
        // Clear out the mContext reference to avoid memory leak.
        mContext = null;
        sUiCallManager = null;
    }

    public void addListener(CallListener listener) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "addListener: " + listener);
        }
        mCallListeners.add(listener);
    }

    public void removeListener(CallListener listener) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "removeListener: " + listener);
        }
        mCallListeners.remove(listener);
    }

    protected void placeCall(String number) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "placeCall: " + number);
        }
        Uri uri = Uri.fromParts("tel", number, null);
        Log.d(TAG, "android.telecom.TelecomManager#placeCall: " + uri);
        mTelecomManager.placeCall(uri, null);
    }

    public void answerCall(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "answerCall: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.answer(0);
        }
    }

    public void rejectCall(UiCall uiCall, boolean rejectWithMessage, String textMessage) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "rejectCall: " + uiCall + ", rejectWithMessage: " + rejectWithMessage
                    + "textMessage: " + textMessage);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.reject(rejectWithMessage, textMessage);
        }
    }

    public void disconnectCall(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "disconnectCall: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.disconnect();
        }
    }

    public List<UiCall> getCalls() {
        return new ArrayList<>(mCallMapping.keySet());
    }

    public boolean getMuted() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "getMuted");
        }
        if (mInCallService == null) {
            return false;
        }
        CallAudioState audioState = mInCallService.getCallAudioState();
        return audioState != null && audioState.isMuted();
    }

    public void setMuted(boolean muted) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "setMuted: " + muted);
        }
        if (mInCallService == null) {
            return;
        }
        mInCallService.setMuted(muted);
    }

    public int getSupportedAudioRouteMask() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "getSupportedAudioRouteMask");
        }

        CallAudioState audioState = getCallAudioStateOrNull();
        return audioState != null ? audioState.getSupportedRouteMask() : 0;
    }

    public List<Integer> getSupportedAudioRoute() {
        List<Integer> audioRouteList = new ArrayList<>();

        boolean isBluetoothPhoneCall = isBluetoothCall();
        if (isBluetoothPhoneCall) {
            // if this is bluetooth phone call, we can only select audio route between vehicle
            // and phone.
            // Vehicle speaker route.
            audioRouteList.add(CallAudioState.ROUTE_BLUETOOTH);
            // Headset route.
            audioRouteList.add(CallAudioState.ROUTE_EARPIECE);
        } else {
            // Most likely we are making phone call with on board SIM card.
            int supportedAudioRouteMask = getSupportedAudioRouteMask();

            if ((supportedAudioRouteMask & CallAudioState.ROUTE_EARPIECE) != 0) {
                audioRouteList.add(CallAudioState.ROUTE_EARPIECE);
            } else if ((supportedAudioRouteMask & CallAudioState.ROUTE_BLUETOOTH) != 0) {
                audioRouteList.add(CallAudioState.ROUTE_BLUETOOTH);
            } else if ((supportedAudioRouteMask & CallAudioState.ROUTE_WIRED_HEADSET) != 0) {
                audioRouteList.add(CallAudioState.ROUTE_WIRED_HEADSET);
            } else if ((supportedAudioRouteMask & CallAudioState.ROUTE_SPEAKER) != 0) {
                audioRouteList.add(CallAudioState.ROUTE_SPEAKER);
            }
        }

        return audioRouteList;
    }

    public boolean isBluetoothCall() {
        PhoneAccountHandle phoneAccountHandle =
                mTelecomManager.getUserSelectedOutgoingPhoneAccount();
        if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
            return HFP_CLIENT_CONNECTION_SERVICE_CLASS_NAME.equals(
                    phoneAccountHandle.getComponentName().getClassName());
        } else {
            return false;
        }
    }

    public int getAudioRoute() {
        CallAudioState audioState = getCallAudioStateOrNull();
        int audioRoute = audioState != null ? audioState.getRoute() : 0;
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "getAudioRoute " + audioRoute);
        }
        return audioRoute;
    }

    /**
     * Re-route the audio out phone of the ongoing phone call.
     */
    public void setAudioRoute(@CallAudioRoute int audioRoute) {
        if (mBluetoothHeadsetClient != null && isBluetoothCall()) {
            for (BluetoothDevice device : mBluetoothHeadsetClient.getConnectedDevices()) {
                List<BluetoothHeadsetClientCall> currentCalls =
                        mBluetoothHeadsetClient.getCurrentCalls(device);
                if (currentCalls != null && !currentCalls.isEmpty()) {
                    if (audioRoute == CallAudioState.ROUTE_BLUETOOTH) {
                        mBluetoothHeadsetClient.connectAudio(device);
                    } else if ((audioRoute & CallAudioState.ROUTE_WIRED_OR_EARPIECE) != 0) {
                        mBluetoothHeadsetClient.disconnectAudio(device);
                    }
                }
            }
        }
        // TODO: Implement routing audio if current call is not a bluetooth call.
    }

    public void holdCall(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "holdCall: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.hold();
        }
    }

    public void unholdCall(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "unholdCall: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.unhold();
        }
    }

    public void playDtmfTone(UiCall uiCall, char digit) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "playDtmfTone: call: " + uiCall + ", digit: " + digit);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.playDtmfTone(digit);
        }
    }

    public void stopDtmfTone(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "stopDtmfTone: call: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.stopDtmfTone();
        }
    }

    public void postDialContinue(UiCall uiCall, boolean proceed) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "postDialContinue: call: " + uiCall + ", proceed: " + proceed);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.postDialContinue(proceed);
        }
    }

    public void conference(UiCall uiCall, UiCall otherUiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "conference: call: " + uiCall + ", otherCall: " + otherUiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        Call otherTelecomCall = mCallMapping.get(otherUiCall);
        if (telecomCall != null) {
            telecomCall.conference(otherTelecomCall);
        }
    }

    public void splitFromConference(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "splitFromConference: call: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.splitFromConference();
        }
    }

    private UiCall doTelecomCallAdded(final Call telecomCall) {
        Log.d(TAG, "doTelecomCallAdded: " + telecomCall);

        UiCall uiCall = getOrCreateCallContainer(telecomCall);
        telecomCall.registerCallback(new TelecomCallListener(this, uiCall));
        for (CallListener listener : mCallListeners) {
            listener.onCallAdded(uiCall);
        }
        Log.d(TAG, "Call backs registered");

        if (telecomCall.getState() == Call.STATE_SELECT_PHONE_ACCOUNT) {
            // TODO(b/26189994): need to show Phone Account picker to let user choose a phone
            // account. It should be an account from TelecomManager#getCallCapablePhoneAccounts
            // list.
            Log.w(TAG, "Need to select phone account for the given call: " + telecomCall + ", "
                    + "but this feature is not implemented yet.");
            telecomCall.disconnect();
        }
        return uiCall;
    }

    private void doTelecomCallRemoved(Call telecomCall) {
        UiCall uiCall = getOrCreateCallContainer(telecomCall);

        mCallMapping.remove(uiCall);

        for (CallListener listener : mCallListeners) {
            listener.onCallRemoved(uiCall);
        }
    }

    private void doCallAudioStateChanged(CallAudioState audioState) {
        for (CallListener listener : mCallListeners) {
            listener.onAudioStateChanged(audioState.isMuted(), audioState.getRoute(),
                    audioState.getSupportedRouteMask());
        }
    }

    private void onStateChanged(UiCall uiCall, int state) {
        for (CallListener listener : mCallListeners) {
            listener.onCallStateChanged(uiCall, state);
        }
    }

    private void onCallUpdated(UiCall uiCall) {
        for (CallListener listener : mCallListeners) {
            listener.onCallUpdated(uiCall);
        }
    }

    private UiCall getOrCreateCallContainer(Call telecomCall) {
        for (Map.Entry<UiCall, Call> entry : mCallMapping.entrySet()) {
            if (entry.getValue() == telecomCall) {
                return entry.getKey();
            }
        }

        UiCall uiCall = new UiCall(nextCarPhoneCallId++);
        updateCallContainerFromTelecom(uiCall, telecomCall);
        mCallMapping.put(uiCall, telecomCall);
        return uiCall;
    }

    private static void updateCallContainerFromTelecom(UiCall uiCall, Call telecomCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "updateCallContainerFromTelecom: call: " + uiCall + ", telecomCall: "
                    + telecomCall);
        }

        uiCall.setState(telecomCall.getState());
        uiCall.setHasChildren(!telecomCall.getChildren().isEmpty());
        uiCall.setHasParent(telecomCall.getParent() != null);

        Call.Details details = telecomCall.getDetails();
        if (details == null) {
            return;
        }

        uiCall.setConnectTimeMillis(details.getConnectTimeMillis());

        DisconnectCause cause = details.getDisconnectCause();
        uiCall.setDisconnectCause(cause == null ? null : cause.getLabel());

        GatewayInfo gatewayInfo = details.getGatewayInfo();
        uiCall.setGatewayInfoOriginalAddress(
                gatewayInfo == null ? null : gatewayInfo.getOriginalAddress());

        String number = "";
        if (gatewayInfo != null) {
            number = gatewayInfo.getOriginalAddress().getSchemeSpecificPart();
        } else if (details.getHandle() != null) {
            number = details.getHandle().getSchemeSpecificPart();
        }
        uiCall.setNumber(number);
    }

    private CallAudioState getCallAudioStateOrNull() {
        return mInCallService != null ? mInCallService.getCallAudioState() : null;
    }

    /** Returns a first call that matches at least one provided call state */
    public UiCall getCallWithState(int... callStates) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "getCallWithState: " + callStates);
        }
        for (UiCall call : getCalls()) {
            for (int callState : callStates) {
                if (call.getState() == callState) {
                    return call;
                }
            }
        }
        return null;
    }

    public UiCall getPrimaryCall() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "getPrimaryCall");
        }
        List<UiCall> calls = getCalls();
        if (calls.isEmpty()) {
            return null;
        }

        Collections.sort(calls, getCallComparator());
        UiCall uiCall = calls.get(0);
        if (uiCall.hasParent()) {
            return null;
        }
        return uiCall;
    }

    public UiCall getSecondaryCall() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "getSecondaryCall");
        }
        List<UiCall> calls = getCalls();
        if (calls.size() < 2) {
            return null;
        }

        Collections.sort(calls, getCallComparator());
        UiCall uiCall = calls.get(1);
        if (uiCall.hasParent()) {
            return null;
        }
        return uiCall;
    }

    public static final int CAN_PLACE_CALL_RESULT_OK = 0;
    public static final int CAN_PLACE_CALL_RESULT_NETWORK_UNAVAILABLE = 1;
    public static final int CAN_PLACE_CALL_RESULT_HFP_UNAVAILABLE = 2;
    public static final int CAN_PLACE_CALL_RESULT_AIRPLANE_MODE = 3;

    public int getCanPlaceCallStatus(String number, boolean bluetoothRequired) {
        // TODO(b/26191392): figure out the logic for projected and embedded modes
        return CAN_PLACE_CALL_RESULT_OK;
    }

    public String getFailToPlaceCallMessage(int canPlaceCallResult) {
        switch (canPlaceCallResult) {
            case CAN_PLACE_CALL_RESULT_OK:
                return "";
            case CAN_PLACE_CALL_RESULT_HFP_UNAVAILABLE:
                return mContext.getString(R.string.error_no_hfp);
            case CAN_PLACE_CALL_RESULT_AIRPLANE_MODE:
                return mContext.getString(R.string.error_airplane_mode);
            case CAN_PLACE_CALL_RESULT_NETWORK_UNAVAILABLE:
            default:
                return mContext.getString(R.string.error_network_not_available);
        }
    }

    /** Places call only if there's no outgoing call right now */
    public void safePlaceCall(String number, boolean bluetoothRequired) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "safePlaceCall: " + number);
        }

        int placeCallStatus = getCanPlaceCallStatus(number, bluetoothRequired);
        if (placeCallStatus != CAN_PLACE_CALL_RESULT_OK) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "Unable to place a call: " + placeCallStatus);
            }
            return;
        }

        UiCall outgoingCall = getCallWithState(
                Call.STATE_CONNECTING, Call.STATE_NEW, Call.STATE_DIALING);
        if (outgoingCall == null) {
            long now = Calendar.getInstance().getTimeInMillis();
            if (now - mLastPlacedCallTimeMs > MIN_TIME_BETWEEN_CALLS_MS) {
                placeCall(number);
                mLastPlacedCallTimeMs = now;
            } else {
                if (Log.isLoggable(TAG, Log.INFO)) {
                    Log.i(TAG, "You have to wait " + MIN_TIME_BETWEEN_CALLS_MS
                            + "ms between making calls");
                }
            }
        }
    }

    public void callVoicemail() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "callVoicemail");
        }

        String voicemailNumber = TelecomUtils.getVoicemailNumber(mContext);
        if (TextUtils.isEmpty(voicemailNumber)) {
            Log.w(TAG, "Unable to get voicemail number.");
            return;
        }
        safePlaceCall(voicemailNumber, false);
    }

    /**
     * Returns the call types for the given number of items in the cursor.
     * <p/>
     * It uses the next {@code count} rows in the cursor to extract the types.
     * <p/>
     * Its position in the cursor is unchanged by this function.
     */
    public int[] getCallTypes(Cursor cursor, int count) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "getCallTypes: cursor: " + cursor + ", count: " + count);
        }

        int position = cursor.getPosition();
        int[] callTypes = new int[count];
        String voicemailNumber = mTelephonyManager.getVoiceMailNumber();
        int column;
        for (int index = 0; index < count; ++index) {
            column = cursor.getColumnIndex(CallLog.Calls.NUMBER);
            String phoneNumber = cursor.getString(column);
            if (phoneNumber != null && phoneNumber.equals(voicemailNumber)) {
                callTypes[index] = PhoneLoader.VOICEMAIL_TYPE;
            } else {
                column = cursor.getColumnIndex(CallLog.Calls.TYPE);
                callTypes[index] = cursor.getInt(column);
            }
            cursor.moveToNext();
        }
        cursor.moveToPosition(position);
        return callTypes;
    }

    private static Comparator<UiCall> getCallComparator() {
        return new Comparator<UiCall>() {
            @Override
            public int compare(UiCall call, UiCall otherCall) {
                if (call.hasParent() && !otherCall.hasParent()) {
                    return 1;
                } else if (!call.hasParent() && otherCall.hasParent()) {
                    return -1;
                }
                int carCallRank = sCallStateRank.indexOf(call.getState());
                int otherCarCallRank = sCallStateRank.indexOf(otherCall.getState());

                return otherCarCallRank - carCallRank;
            }
        };
    }

    private static class TelecomCallListener extends Call.Callback {
        private final WeakReference<UiCallManager> mCarTelecomMangerRef;
        private final WeakReference<UiCall> mCallContainerRef;

        TelecomCallListener(UiCallManager carTelecomManager, UiCall uiCall) {
            mCarTelecomMangerRef = new WeakReference<>(carTelecomManager);
            mCallContainerRef = new WeakReference<>(uiCall);
        }

        @Override
        public void onStateChanged(Call telecomCall, int state) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onStateChanged: " + state);
            }
            UiCallManager manager = mCarTelecomMangerRef.get();
            UiCall call = mCallContainerRef.get();
            if (manager != null && call != null) {
                call.setState(state);
                manager.onStateChanged(call, state);
            }
        }

        @Override
        public void onParentChanged(Call telecomCall, Call parent) {
            doCallUpdated(telecomCall);
        }

        @Override
        public void onCallDestroyed(Call telecomCall) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onCallDestroyed");
            }
        }

        @Override
        public void onDetailsChanged(Call telecomCall, Call.Details details) {
            doCallUpdated(telecomCall);
        }

        @Override
        public void onVideoCallChanged(Call telecomCall, InCallService.VideoCall videoCall) {
            doCallUpdated(telecomCall);
        }

        @Override
        public void onCannedTextResponsesLoaded(Call telecomCall,
                List<String> cannedTextResponses) {
            doCallUpdated(telecomCall);
        }

        @Override
        public void onChildrenChanged(Call telecomCall, List<Call> children) {
            doCallUpdated(telecomCall);
        }

        private void doCallUpdated(Call telecomCall) {
            UiCallManager manager = mCarTelecomMangerRef.get();
            UiCall uiCall = mCallContainerRef.get();
            if (manager != null && uiCall != null) {
                updateCallContainerFromTelecom(uiCall, telecomCall);
                manager.onCallUpdated(uiCall);
            }
        }
    }
}
