/*
 * Copyright (C) 2009 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.settings.bluetooth;

import com.android.settings.R;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.ServiceListener;

import android.app.AlertDialog;
import android.app.Notification;
import android.app.Service;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;

import java.util.Collection;
import java.util.List;
import java.util.Set;

public final class DockService extends Service implements ServiceListener {

    private static final String TAG = "DockService";

    static final boolean DEBUG = false;

    // Time allowed for the device to be undocked and redocked without severing
    // the bluetooth connection
    private static final long UNDOCKED_GRACE_PERIOD = 1000;

    // Time allowed for the device to be undocked and redocked without turning
    // off Bluetooth
    private static final long DISABLE_BT_GRACE_PERIOD = 2000;

    // Msg for user wanting the UI to setup the dock
    private static final int MSG_TYPE_SHOW_UI = 111;

    // Msg for device docked event
    private static final int MSG_TYPE_DOCKED = 222;

    // Msg for device undocked event
    private static final int MSG_TYPE_UNDOCKED_TEMPORARY = 333;

    // Msg for undocked command to be process after UNDOCKED_GRACE_PERIOD millis
    // since MSG_TYPE_UNDOCKED_TEMPORARY
    private static final int MSG_TYPE_UNDOCKED_PERMANENT = 444;

    // Msg for disabling bt after DISABLE_BT_GRACE_PERIOD millis since
    // MSG_TYPE_UNDOCKED_PERMANENT
    private static final int MSG_TYPE_DISABLE_BT = 555;

    private static final String SHARED_PREFERENCES_NAME = "dock_settings";

    private static final String KEY_DISABLE_BT_WHEN_UNDOCKED = "disable_bt_when_undock";

    private static final String KEY_DISABLE_BT = "disable_bt";

    private static final String KEY_CONNECT_RETRY_COUNT = "connect_retry_count";

    /*
     * If disconnected unexpectedly, reconnect up to 6 times. Each profile counts
     * as one time so it's only 3 times for both profiles on the car dock.
     */
    private static final int MAX_CONNECT_RETRY = 6;

    private static final int INVALID_STARTID = -100;

    // Created in OnCreate()
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private Runnable mRunnable;
    private LocalBluetoothAdapter mLocalAdapter;
    private CachedBluetoothDeviceManager mDeviceManager;
    private LocalBluetoothProfileManager mProfileManager;

    // Normally set after getting a docked event and unset when the connection
    // is severed. One exception is that mDevice could be null if the service
    // was started after the docked event.
    private BluetoothDevice mDevice;

    // Created and used for the duration of the dialog
    private AlertDialog mDialog;
    private LocalBluetoothProfile[] mProfiles;
    private boolean[] mCheckedItems;
    private int mStartIdAssociatedWithDialog;

    // Set while BT is being enabled.
    private BluetoothDevice mPendingDevice;
    private int mPendingStartId;
    private int mPendingTurnOnStartId = INVALID_STARTID;
    private int mPendingTurnOffStartId = INVALID_STARTID;

    @Override
    public void onCreate() {
        if (DEBUG) Log.d(TAG, "onCreate");

        LocalBluetoothManager manager = LocalBluetoothManager.getInstance(this);
        if (manager == null) {
            Log.e(TAG, "Can't get LocalBluetoothManager: exiting");
            return;
        }

        mLocalAdapter = manager.getBluetoothAdapter();
        mDeviceManager = manager.getCachedDeviceManager();
        mProfileManager = manager.getProfileManager();
        if (mProfileManager == null) {
            Log.e(TAG, "Can't get LocalBluetoothProfileManager: exiting");
            return;
        }

        HandlerThread thread = new HandlerThread("DockService");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onDestroy() {
        if (DEBUG) Log.d(TAG, "onDestroy");
        mRunnable = null;
        if (mDialog != null) {
            mDialog.dismiss();
            mDialog = null;
        }
        if (mProfileManager != null) {
            mProfileManager.removeServiceListener(this);
        }
        if (mServiceLooper != null) {
            mServiceLooper.quit();
        }

        mLocalAdapter = null;
        mDeviceManager = null;
        mProfileManager = null;
        mServiceLooper = null;
        mServiceHandler = null;
    }

    @Override
    public IBinder onBind(Intent intent) {
        // not supported
        return null;
    }

    private SharedPreferences getPrefs() {
        return getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (DEBUG) Log.d(TAG, "onStartCommand startId: " + startId + " flags: " + flags);

        if (intent == null) {
            // Nothing to process, stop.
            if (DEBUG) Log.d(TAG, "START_NOT_STICKY - intent is null.");

            // NOTE: We MUST not call stopSelf() directly, since we need to
            // make sure the wake lock acquired by the Receiver is released.
            DockEventReceiver.finishStartingService(this, startId);
            return START_NOT_STICKY;
        }

        if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
            handleBtStateChange(intent, startId);
            return START_NOT_STICKY;
        }

        /*
         * This assumes that the intent sender has checked that this is a dock
         * and that the intent is for a disconnect
         */
        final SharedPreferences prefs = getPrefs();
        if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
            BluetoothDevice disconnectedDevice = intent
                    .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            int retryCount = prefs.getInt(KEY_CONNECT_RETRY_COUNT, 0);
            if (retryCount < MAX_CONNECT_RETRY) {
                prefs.edit().putInt(KEY_CONNECT_RETRY_COUNT, retryCount + 1).apply();
                handleUnexpectedDisconnect(disconnectedDevice, mProfileManager.getHeadsetProfile(), startId);
            }
            return START_NOT_STICKY;
        } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
            BluetoothDevice disconnectedDevice = intent
                    .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

            int retryCount = prefs.getInt(KEY_CONNECT_RETRY_COUNT, 0);
            if (retryCount < MAX_CONNECT_RETRY) {
                prefs.edit().putInt(KEY_CONNECT_RETRY_COUNT, retryCount + 1).apply();
                handleUnexpectedDisconnect(disconnectedDevice, mProfileManager.getA2dpProfile(), startId);
            }
            return START_NOT_STICKY;
        }

        Message msg = parseIntent(intent);
        if (msg == null) {
            // Bad intent
            if (DEBUG) Log.d(TAG, "START_NOT_STICKY - Bad intent.");
            DockEventReceiver.finishStartingService(this, startId);
            return START_NOT_STICKY;
        }

        if (msg.what == MSG_TYPE_DOCKED) {
            prefs.edit().remove(KEY_CONNECT_RETRY_COUNT).apply();
        }

        msg.arg2 = startId;
        processMessage(msg);

        return START_NOT_STICKY;
    }

    private final class ServiceHandler extends Handler {
        private ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            processMessage(msg);
        }
    }

    // This method gets messages from both onStartCommand and mServiceHandler/mServiceLooper
    private synchronized void processMessage(Message msg) {
        int msgType = msg.what;
        final int state = msg.arg1;
        final int startId = msg.arg2;
        BluetoothDevice device = null;
        if (msg.obj != null) {
            device = (BluetoothDevice) msg.obj;
        }

        if(DEBUG) Log.d(TAG, "processMessage: " + msgType + " state: " + state + " device = "
                + (device == null ? "null" : device.toString()));

        boolean deferFinishCall = false;

        switch (msgType) {
            case MSG_TYPE_SHOW_UI:
                createDialog(device, state, startId);
                break;

            case MSG_TYPE_DOCKED:
                deferFinishCall = msgTypeDocked(device, state, startId);
                break;

            case MSG_TYPE_UNDOCKED_PERMANENT:
                deferFinishCall = msgTypeUndockedPermanent(device, startId);
                break;

            case MSG_TYPE_UNDOCKED_TEMPORARY:
                msgTypeUndockedTemporary(device, state, startId);
                break;

            case MSG_TYPE_DISABLE_BT:
                deferFinishCall = msgTypeDisableBluetooth(startId);
                break;
        }

        if (mDialog == null && mPendingDevice == null && msgType != MSG_TYPE_UNDOCKED_TEMPORARY
                && !deferFinishCall) {
            // NOTE: We MUST not call stopSelf() directly, since we need to
            // make sure the wake lock acquired by the Receiver is released.
            DockEventReceiver.finishStartingService(this, startId);
        }
    }

    private boolean msgTypeDisableBluetooth(int startId) {
        if (DEBUG) {
            Log.d(TAG, "BT DISABLE");
        }
        final SharedPreferences prefs = getPrefs();
        if (mLocalAdapter.disable()) {
            prefs.edit().remove(KEY_DISABLE_BT_WHEN_UNDOCKED).apply();
            return false;
        } else {
            // disable() returned an error. Persist a flag to disable BT later
            prefs.edit().putBoolean(KEY_DISABLE_BT, true).apply();
            mPendingTurnOffStartId = startId;
            if(DEBUG) {
                Log.d(TAG, "disable failed. try again later " + startId);
            }
            return true;
        }
    }

    private void msgTypeUndockedTemporary(BluetoothDevice device, int state,
            int startId) {
        // Undocked event received. Queue a delayed msg to sever connection
        Message newMsg = mServiceHandler.obtainMessage(MSG_TYPE_UNDOCKED_PERMANENT, state,
                startId, device);
        mServiceHandler.sendMessageDelayed(newMsg, UNDOCKED_GRACE_PERIOD);
    }

    private boolean msgTypeUndockedPermanent(BluetoothDevice device, int startId) {
        // Grace period passed. Disconnect.
        handleUndocked(device);
        final SharedPreferences prefs = getPrefs();

        if (DEBUG) {
            Log.d(TAG, "DISABLE_BT_WHEN_UNDOCKED = "
                    + prefs.getBoolean(KEY_DISABLE_BT_WHEN_UNDOCKED, false));
        }

        if (prefs.getBoolean(KEY_DISABLE_BT_WHEN_UNDOCKED, false)) {
            if (hasOtherConnectedDevices(device)) {
                // Don't disable BT if something is connected
                prefs.edit().remove(KEY_DISABLE_BT_WHEN_UNDOCKED).apply();
            } else {
                // BT was disabled when we first docked
                if (DEBUG) {
                    Log.d(TAG, "QUEUED BT DISABLE");
                }
                // Queue a delayed msg to disable BT
                Message newMsg = mServiceHandler.obtainMessage(
                        MSG_TYPE_DISABLE_BT, 0, startId, null);
                mServiceHandler.sendMessageDelayed(newMsg,
                        DISABLE_BT_GRACE_PERIOD);
                return true;
            }
        }
        return false;
    }

    private boolean msgTypeDocked(BluetoothDevice device, final int state,
            final int startId) {
        if (DEBUG) {
            // TODO figure out why hasMsg always returns false if device
            // is supplied
            Log.d(TAG, "1 Has undock perm msg = "
                    + mServiceHandler.hasMessages(MSG_TYPE_UNDOCKED_PERMANENT, mDevice));
            Log.d(TAG, "2 Has undock perm msg = "
                    + mServiceHandler.hasMessages(MSG_TYPE_UNDOCKED_PERMANENT, device));
        }

        mServiceHandler.removeMessages(MSG_TYPE_UNDOCKED_PERMANENT);
        mServiceHandler.removeMessages(MSG_TYPE_DISABLE_BT);
        getPrefs().edit().remove(KEY_DISABLE_BT).apply();

        if (device != null && !device.equals(mDevice)) {
            if (mDevice != null) {
                // Not expected. Cleanup/undock existing
                handleUndocked(mDevice);
            }

            mDevice = device;

            // Register first in case LocalBluetoothProfileManager
            // becomes ready after isManagerReady is called and it
            // would be too late to register a service listener.
            mProfileManager.addServiceListener(this);
            if (mProfileManager.isManagerReady()) {
                handleDocked(device, state, startId);
                // Not needed after all
                mProfileManager.removeServiceListener(this);
            } else {
                final BluetoothDevice d = device;
                mRunnable = new Runnable() {
                    public void run() {
                        handleDocked(d, state, startId);  // FIXME: WTF runnable here?
                    }
                };
                return true;
            }
        }
        return false;
    }

    synchronized boolean hasOtherConnectedDevices(BluetoothDevice dock) {
        Collection<CachedBluetoothDevice> cachedDevices = mDeviceManager.getCachedDevicesCopy();
        Set<BluetoothDevice> btDevices = mLocalAdapter.getBondedDevices();
        if (btDevices == null || cachedDevices == null || btDevices.isEmpty()) {
            return false;
        }
        if(DEBUG) {
            Log.d(TAG, "btDevices = " + btDevices.size());
            Log.d(TAG, "cachedDeviceUIs = " + cachedDevices.size());
        }

        for (CachedBluetoothDevice deviceUI : cachedDevices) {
            BluetoothDevice btDevice = deviceUI.getDevice();
            if (!btDevice.equals(dock) && btDevices.contains(btDevice) && deviceUI
                    .isConnected()) {
                if(DEBUG) Log.d(TAG, "connected deviceUI = " + deviceUI.getName());
                return true;
            }
        }
        return false;
    }

    private Message parseIntent(Intent intent) {
        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, -1234);

        if (DEBUG) {
            Log.d(TAG, "Action: " + intent.getAction() + " State:" + state
                    + " Device: " + (device == null ? "null" : device.getAliasName()));
        }

        if (device == null) {
            Log.w(TAG, "device is null");
            return null;
        }

        int msgType;
        switch (state) {
            case Intent.EXTRA_DOCK_STATE_UNDOCKED:
                msgType = MSG_TYPE_UNDOCKED_TEMPORARY;
                break;
            case Intent.EXTRA_DOCK_STATE_DESK:
            case Intent.EXTRA_DOCK_STATE_LE_DESK:
            case Intent.EXTRA_DOCK_STATE_HE_DESK:
            case Intent.EXTRA_DOCK_STATE_CAR:
                if (DockEventReceiver.ACTION_DOCK_SHOW_UI.equals(intent.getAction())) {
                    msgType = MSG_TYPE_SHOW_UI;
                } else {
                    msgType = MSG_TYPE_DOCKED;
                }
                break;
            default:
                return null;
        }

        return mServiceHandler.obtainMessage(msgType, state, 0, device);
    }

    private void createDialog(BluetoothDevice device,
            int state, int startId) {
        if (mDialog != null) {
            // Shouldn't normally happen
            mDialog.dismiss();
            mDialog = null;
        }
        mDevice = device;
        switch (state) {
            case Intent.EXTRA_DOCK_STATE_CAR:
            case Intent.EXTRA_DOCK_STATE_DESK:
            case Intent.EXTRA_DOCK_STATE_LE_DESK:
            case Intent.EXTRA_DOCK_STATE_HE_DESK:
                break;
            default:
                return;
        }

        startForeground(0, new Notification());

        // Device in a new dock.
        boolean firstTime = !LocalBluetoothPreferences.hasDockAutoConnectSetting(this, device.getAddress());

        CharSequence[] items = initBtSettings(device, state, firstTime);

        final AlertDialog.Builder ab = new AlertDialog.Builder(this);
        ab.setTitle(getString(R.string.bluetooth_dock_settings_title));

        // Profiles
        ab.setMultiChoiceItems(items, mCheckedItems, mMultiClickListener);

        // Remember this settings
        LayoutInflater inflater = (LayoutInflater)
                getSystemService(LAYOUT_INFLATER_SERVICE);
        float pixelScaleFactor = getResources().getDisplayMetrics().density;
        View view = inflater.inflate(R.layout.remember_dock_setting, null);
        CheckBox rememberCheckbox = (CheckBox) view.findViewById(R.id.remember);

        // check "Remember setting" by default if no value was saved
        boolean checked = firstTime || LocalBluetoothPreferences.getDockAutoConnectSetting(this, device.getAddress());
        rememberCheckbox.setChecked(checked);
        rememberCheckbox.setOnCheckedChangeListener(mCheckedChangeListener);
        int viewSpacingLeft = (int) (14 * pixelScaleFactor);
        int viewSpacingRight = (int) (14 * pixelScaleFactor);
        ab.setView(view, viewSpacingLeft, 0 /* top */, viewSpacingRight, 0 /* bottom */);
        if (DEBUG) {
            Log.d(TAG, "Auto connect = "
                    + LocalBluetoothPreferences.getDockAutoConnectSetting(this, device.getAddress()));
        }

        // Ok Button
        ab.setPositiveButton(getString(android.R.string.ok), mClickListener);

        mStartIdAssociatedWithDialog = startId;
        mDialog = ab.create();
        mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
        mDialog.setOnDismissListener(mDismissListener);
        mDialog.show();
    }

    // Called when the individual bt profiles are clicked.
    private final DialogInterface.OnMultiChoiceClickListener mMultiClickListener =
            new DialogInterface.OnMultiChoiceClickListener() {
                public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                    if (DEBUG) {
                        Log.d(TAG, "Item " + which + " changed to " + isChecked);
                    }
                    mCheckedItems[which] = isChecked;
                }
            };


    // Called when the "Remember" Checkbox is clicked
    private final CompoundButton.OnCheckedChangeListener mCheckedChangeListener =
            new CompoundButton.OnCheckedChangeListener() {
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if (DEBUG) {
                        Log.d(TAG, "onCheckedChanged: Remember Settings = " + isChecked);
                    }
                    if (mDevice != null) {
                        LocalBluetoothPreferences.saveDockAutoConnectSetting(
                                DockService.this, mDevice.getAddress(), isChecked);
                    }
                }
            };


    // Called when the dialog is dismissed
    private final DialogInterface.OnDismissListener mDismissListener =
            new DialogInterface.OnDismissListener() {
                public void onDismiss(DialogInterface dialog) {
                    // NOTE: We MUST not call stopSelf() directly, since we need to
                    // make sure the wake lock acquired by the Receiver is released.
                    if (mPendingDevice == null) {
                        DockEventReceiver.finishStartingService(
                                DockService.this, mStartIdAssociatedWithDialog);
                    }
                    stopForeground(true);
                }
            };

    // Called when clicked on the OK button
    private final DialogInterface.OnClickListener mClickListener =
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    if (which == DialogInterface.BUTTON_POSITIVE
                            && mDevice != null) {
                        if (!LocalBluetoothPreferences
                                .hasDockAutoConnectSetting(
                                        DockService.this,
                                        mDevice.getAddress())) {
                            LocalBluetoothPreferences
                                    .saveDockAutoConnectSetting(
                                            DockService.this,
                                            mDevice.getAddress(), true);
                        }

                        applyBtSettings(mDevice, mStartIdAssociatedWithDialog);
                    }
                }
            };

    private CharSequence[] initBtSettings(BluetoothDevice device,
            int state, boolean firstTime) {
        // TODO Avoid hardcoding dock and profiles. Read from system properties
        int numOfProfiles;
        switch (state) {
            case Intent.EXTRA_DOCK_STATE_DESK:
            case Intent.EXTRA_DOCK_STATE_LE_DESK:
            case Intent.EXTRA_DOCK_STATE_HE_DESK:
                numOfProfiles = 1;
                break;
            case Intent.EXTRA_DOCK_STATE_CAR:
                numOfProfiles = 2;
                break;
            default:
                return null;
        }

        mProfiles = new LocalBluetoothProfile[numOfProfiles];
        mCheckedItems = new boolean[numOfProfiles];
        CharSequence[] items = new CharSequence[numOfProfiles];

        // FIXME: convert switch to something else
        switch (state) {
            case Intent.EXTRA_DOCK_STATE_CAR:
                items[0] = getString(R.string.bluetooth_dock_settings_headset);
                items[1] = getString(R.string.bluetooth_dock_settings_a2dp);
                mProfiles[0] = mProfileManager.getHeadsetProfile();
                mProfiles[1] = mProfileManager.getA2dpProfile();
                if (firstTime) {
                    // Enable by default for car dock
                    mCheckedItems[0] = true;
                    mCheckedItems[1] = true;
                } else {
                    mCheckedItems[0] = mProfiles[0].isPreferred(device);
                    mCheckedItems[1] = mProfiles[1].isPreferred(device);
                }
                break;

            case Intent.EXTRA_DOCK_STATE_DESK:
            case Intent.EXTRA_DOCK_STATE_LE_DESK:
            case Intent.EXTRA_DOCK_STATE_HE_DESK:
                items[0] = getString(R.string.bluetooth_dock_settings_a2dp);
                mProfiles[0] = mProfileManager.getA2dpProfile();
                if (firstTime) {
                    // Disable by default for desk dock
                    mCheckedItems[0] = false;
                } else {
                    mCheckedItems[0] = mProfiles[0].isPreferred(device);
                }
                break;
        }
        return items;
    }

    // TODO: move to background thread to fix strict mode warnings
    private void handleBtStateChange(Intent intent, int startId) {
        int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
        synchronized (this) {
            if(DEBUG) Log.d(TAG, "BtState = " + btState + " mPendingDevice = " + mPendingDevice);
            if (btState == BluetoothAdapter.STATE_ON) {
                handleBluetoothStateOn(startId);
            } else if (btState == BluetoothAdapter.STATE_TURNING_OFF) {
                // Remove the flag to disable BT if someone is turning off bt.
                // The rational is that:
                // a) if BT is off at undock time, no work needs to be done
                // b) if BT is on at undock time, the user wants it on.
                getPrefs().edit().remove(KEY_DISABLE_BT_WHEN_UNDOCKED).apply();
                DockEventReceiver.finishStartingService(this, startId);
            } else if (btState == BluetoothAdapter.STATE_OFF) {
                // Bluetooth was turning off as we were trying to turn it on.
                // Let's try again
                if(DEBUG) Log.d(TAG, "Bluetooth = OFF mPendingDevice = " + mPendingDevice);

                if (mPendingTurnOffStartId != INVALID_STARTID) {
                    DockEventReceiver.finishStartingService(this, mPendingTurnOffStartId);
                    getPrefs().edit().remove(KEY_DISABLE_BT).apply();
                    mPendingTurnOffStartId = INVALID_STARTID;
                }

                if (mPendingDevice != null) {
                    mLocalAdapter.enable();
                    mPendingTurnOnStartId = startId;
                } else {
                    DockEventReceiver.finishStartingService(this, startId);
                }
            }
        }
    }

    private void handleBluetoothStateOn(int startId) {
        if (mPendingDevice != null) {
            if (mPendingDevice.equals(mDevice)) {
                if(DEBUG) {
                    Log.d(TAG, "applying settings");
                }
                applyBtSettings(mPendingDevice, mPendingStartId);
            } else if(DEBUG) {
                Log.d(TAG, "mPendingDevice  (" + mPendingDevice + ") != mDevice ("
                        + mDevice + ')');
            }

            mPendingDevice = null;
            DockEventReceiver.finishStartingService(this, mPendingStartId);
        } else {
            final SharedPreferences prefs = getPrefs();
            if (DEBUG) {
                Log.d(TAG, "A DISABLE_BT_WHEN_UNDOCKED = "
                        + prefs.getBoolean(KEY_DISABLE_BT_WHEN_UNDOCKED, false));
            }
            // Reconnect if docked and bluetooth was enabled by user.
            Intent i = registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
            if (i != null) {
                int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE,
                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
                if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
                    BluetoothDevice device = i
                            .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    if (device != null) {
                        connectIfEnabled(device);
                    }
                } else if (prefs.getBoolean(KEY_DISABLE_BT, false)
                        && mLocalAdapter.disable()) {
                    mPendingTurnOffStartId = startId;
                    prefs.edit().remove(KEY_DISABLE_BT).apply();
                    return;
                }
            }
        }

        if (mPendingTurnOnStartId != INVALID_STARTID) {
            DockEventReceiver.finishStartingService(this, mPendingTurnOnStartId);
            mPendingTurnOnStartId = INVALID_STARTID;
        }

        DockEventReceiver.finishStartingService(this, startId);
    }

    private synchronized void handleUnexpectedDisconnect(BluetoothDevice disconnectedDevice,
            LocalBluetoothProfile profile, int startId) {
        if (DEBUG) {
            Log.d(TAG, "handling failed connect for " + disconnectedDevice);
        }

            // Reconnect if docked.
            if (disconnectedDevice != null) {
                // registerReceiver can't be called from a BroadcastReceiver
                Intent intent = registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
                if (intent != null) {
                    int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
                            Intent.EXTRA_DOCK_STATE_UNDOCKED);
                    if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
                        BluetoothDevice dockedDevice = intent
                                .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                        if (dockedDevice != null && dockedDevice.equals(disconnectedDevice)) {
                            CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(
                                    dockedDevice);
                            cachedDevice.connectProfile(profile);
                        }
                    }
                }
            }

            DockEventReceiver.finishStartingService(this, startId);
    }

    private synchronized void connectIfEnabled(BluetoothDevice device) {
        CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(
                device);
        List<LocalBluetoothProfile> profiles = cachedDevice.getConnectableProfiles();
        for (LocalBluetoothProfile profile : profiles) {
            if (profile.getPreferred(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) {
                cachedDevice.connect(false);
                return;
            }
        }
    }

    private synchronized void applyBtSettings(BluetoothDevice device, int startId) {
        if (device == null || mProfiles == null || mCheckedItems == null
                || mLocalAdapter == null) {
            return;
        }

        // Turn on BT if something is enabled
        for (boolean enable : mCheckedItems) {
            if (enable) {
                int btState = mLocalAdapter.getBluetoothState();
                if (DEBUG) {
                    Log.d(TAG, "BtState = " + btState);
                }
                // May have race condition as the phone comes in and out and in the dock.
                // Always turn on BT
                mLocalAdapter.enable();

                // if adapter was previously OFF, TURNING_OFF, or TURNING_ON
                if (btState != BluetoothAdapter.STATE_ON) {
                    if (mPendingDevice != null && mPendingDevice.equals(mDevice)) {
                        return;
                    }

                    mPendingDevice = device;
                    mPendingStartId = startId;
                    if (btState != BluetoothAdapter.STATE_TURNING_ON) {
                        getPrefs().edit().putBoolean(
                                KEY_DISABLE_BT_WHEN_UNDOCKED, true).apply();
                    }
                    return;
                }
            }
        }

        mPendingDevice = null;

        boolean callConnect = false;
        CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(
                device);
        for (int i = 0; i < mProfiles.length; i++) {
            LocalBluetoothProfile profile = mProfiles[i];
            if (DEBUG) Log.d(TAG, profile.toString() + " = " + mCheckedItems[i]);

            if (mCheckedItems[i]) {
                // Checked but not connected
                callConnect = true;
            } else if (!mCheckedItems[i]) {
                // Unchecked, may or may not be connected.
                int status = profile.getConnectionStatus(cachedDevice.getDevice());
                if (status == BluetoothProfile.STATE_CONNECTED) {
                    if (DEBUG) Log.d(TAG, "applyBtSettings - Disconnecting");
                    cachedDevice.disconnect(mProfiles[i]);
                }
            }
            profile.setPreferred(device, mCheckedItems[i]);
            if (DEBUG) {
                if (mCheckedItems[i] != profile.isPreferred(device)) {
                    Log.e(TAG, "Can't save preferred value");
                }
            }
        }

        if (callConnect) {
            if (DEBUG) Log.d(TAG, "applyBtSettings - Connecting");
            cachedDevice.connect(false);
        }
    }

    private synchronized void handleDocked(BluetoothDevice device, int state,
            int startId) {
        if (LocalBluetoothPreferences.getDockAutoConnectSetting(this, device.getAddress())) {
            // Setting == auto connect
            initBtSettings(device, state, false);
            applyBtSettings(mDevice, startId);
        } else {
            createDialog(device, state, startId);
        }
    }

    private synchronized void handleUndocked(BluetoothDevice device) {
        mRunnable = null;
        mProfileManager.removeServiceListener(this);
        if (mDialog != null) {
            mDialog.dismiss();
            mDialog = null;
        }
        mDevice = null;
        mPendingDevice = null;
        CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(device);
        cachedDevice.disconnect();
    }

    private CachedBluetoothDevice getCachedBluetoothDevice(BluetoothDevice device) {
        CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
        if (cachedDevice == null) {
            cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
        }
        return cachedDevice;
    }

    public synchronized void onServiceConnected() {
        if (mRunnable != null) {
            mRunnable.run();
            mRunnable = null;
            mProfileManager.removeServiceListener(this);
        }
    }

    public void onServiceDisconnected() {
        // FIXME: shouldn't I do something on service disconnected too?
    }
}
