// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/dbus/fake_bluetooth_device_client.h"

#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <algorithm>
#include <map>
#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "base/threading/worker_pool.h"
#include "base/time/time.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
#include "chromeos/dbus/fake_bluetooth_agent_service_provider.h"
#include "chromeos/dbus/fake_bluetooth_input_client.h"
#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
#include "dbus/file_descriptor.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace {

// Default interval between simulated events.
const int kSimulationIntervalMs = 750;


void SimulatedProfileSocket(int fd) {
  // Simulate a server-side socket of a profile; read data from the socket,
  // write it back, and then close.
  char buf[1024];
  ssize_t len;
  ssize_t count;

  len = read(fd, buf, sizeof buf);
  if (len < 0) {
    close(fd);
    return;
  }

  count = len;
  len = write(fd, buf, count);
  if (len < 0) {
    close(fd);
    return;
  }

  close(fd);
}

}

namespace chromeos {

const char FakeBluetoothDeviceClient::kPairedDevicePath[] =
    "/fake/hci0/dev0";
const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] =
    "00:11:22:33:44:55";
const char FakeBluetoothDeviceClient::kPairedDeviceName[] =
    "Fake Device";
const uint32 FakeBluetoothDeviceClient::kPairedDeviceClass = 0x000104;

const char FakeBluetoothDeviceClient::kAppleMousePath[] =
    "/fake/hci0/dev1";
const char FakeBluetoothDeviceClient::kAppleMouseAddress[] =
    "28:CF:DA:00:00:00";
const char FakeBluetoothDeviceClient::kAppleMouseName[] =
    "Apple Magic Mouse";
const uint32 FakeBluetoothDeviceClient::kAppleMouseClass = 0x002580;

const char FakeBluetoothDeviceClient::kAppleKeyboardPath[] =
    "/fake/hci0/dev2";
const char FakeBluetoothDeviceClient::kAppleKeyboardAddress[] =
    "28:37:37:00:00:00";
const char FakeBluetoothDeviceClient::kAppleKeyboardName[] =
    "Apple Wireless Keyboard";
const uint32 FakeBluetoothDeviceClient::kAppleKeyboardClass = 0x002540;

const char FakeBluetoothDeviceClient::kVanishingDevicePath[] =
    "/fake/hci0/dev3";
const char FakeBluetoothDeviceClient::kVanishingDeviceAddress[] =
    "01:02:03:04:05:06";
const char FakeBluetoothDeviceClient::kVanishingDeviceName[] =
    "Vanishing Device";
const uint32 FakeBluetoothDeviceClient::kVanishingDeviceClass = 0x000104;

const char FakeBluetoothDeviceClient::kMicrosoftMousePath[] =
    "/fake/hci0/dev4";
const char FakeBluetoothDeviceClient::kMicrosoftMouseAddress[] =
    "7C:ED:8D:00:00:00";
const char FakeBluetoothDeviceClient::kMicrosoftMouseName[] =
    "Microsoft Mouse";
const uint32 FakeBluetoothDeviceClient::kMicrosoftMouseClass = 0x002580;

const char FakeBluetoothDeviceClient::kMotorolaKeyboardPath[] =
    "/fake/hci0/dev5";
const char FakeBluetoothDeviceClient::kMotorolaKeyboardAddress[] =
    "00:0F:F6:00:00:00";
const char FakeBluetoothDeviceClient::kMotorolaKeyboardName[] =
    "Motorola Keyboard";
const uint32 FakeBluetoothDeviceClient::kMotorolaKeyboardClass = 0x002540;

const char FakeBluetoothDeviceClient::kSonyHeadphonesPath[] =
    "/fake/hci0/dev6";
const char FakeBluetoothDeviceClient::kSonyHeadphonesAddress[] =
    "00:24:BE:00:00:00";
const char FakeBluetoothDeviceClient::kSonyHeadphonesName[] =
    "Sony BT-00";
const uint32 FakeBluetoothDeviceClient::kSonyHeadphonesClass = 0x240408;

const char FakeBluetoothDeviceClient::kPhonePath[] =
    "/fake/hci0/dev7";
const char FakeBluetoothDeviceClient::kPhoneAddress[] =
    "20:7D:74:00:00:00";
const char FakeBluetoothDeviceClient::kPhoneName[] =
    "Phone";
const uint32 FakeBluetoothDeviceClient::kPhoneClass = 0x7a020c;

const char FakeBluetoothDeviceClient::kWeirdDevicePath[] =
    "/fake/hci0/dev8";
const char FakeBluetoothDeviceClient::kWeirdDeviceAddress[] =
    "20:7D:74:00:00:01";
const char FakeBluetoothDeviceClient::kWeirdDeviceName[] =
    "Weird Device";
const uint32 FakeBluetoothDeviceClient::kWeirdDeviceClass = 0x7a020c;

const char FakeBluetoothDeviceClient::kUnconnectableDevicePath[] =
    "/fake/hci0/dev9";
const char FakeBluetoothDeviceClient::kUnconnectableDeviceAddress[] =
    "20:7D:74:00:00:02";
const char FakeBluetoothDeviceClient::kUnconnectableDeviceName[] =
    "Unconnectable Device";
const uint32 FakeBluetoothDeviceClient::kUnconnectableDeviceClass = 0x7a020c;

const char FakeBluetoothDeviceClient::kUnpairableDevicePath[] =
    "/fake/hci0/devA";
const char FakeBluetoothDeviceClient::kUnpairableDeviceAddress[] =
    "20:7D:74:00:00:03";
const char FakeBluetoothDeviceClient::kUnpairableDeviceName[] =
    "Unpairable Device";
const uint32 FakeBluetoothDeviceClient::kUnpairableDeviceClass = 0x002540;

FakeBluetoothDeviceClient::Properties::Properties(
    const PropertyChangedCallback& callback)
    : BluetoothDeviceClient::Properties(
          NULL,
          bluetooth_device::kBluetoothDeviceInterface,
          callback) {
}

FakeBluetoothDeviceClient::Properties::~Properties() {
}

void FakeBluetoothDeviceClient::Properties::Get(
    dbus::PropertyBase* property,
    dbus::PropertySet::GetCallback callback) {
  VLOG(1) << "Get " << property->name();
  callback.Run(false);
}

void FakeBluetoothDeviceClient::Properties::GetAll() {
  VLOG(1) << "GetAll";
}

void FakeBluetoothDeviceClient::Properties::Set(
    dbus::PropertyBase *property,
    dbus::PropertySet::SetCallback callback) {
  VLOG(1) << "Set " << property->name();
  if (property->name() == trusted.name()) {
    callback.Run(true);
    property->ReplaceValueWithSetValue();
  } else {
    callback.Run(false);
  }
}


FakeBluetoothDeviceClient::FakeBluetoothDeviceClient()
    : simulation_interval_ms_(kSimulationIntervalMs),
      discovery_simulation_step_(0),
      pairing_cancelled_(false) {
  Properties* properties = new Properties(base::Bind(
      &FakeBluetoothDeviceClient::OnPropertyChanged,
      base::Unretained(this),
      dbus::ObjectPath(kPairedDevicePath)));
  properties->address.ReplaceValue(kPairedDeviceAddress);
  properties->bluetooth_class.ReplaceValue(kPairedDeviceClass);
  properties->name.ReplaceValue("Fake Device (Name)");
  properties->alias.ReplaceValue(kPairedDeviceName);
  properties->paired.ReplaceValue(true);
  properties->trusted.ReplaceValue(true);
  properties->adapter.ReplaceValue(
      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));

  std::vector<std::string> uuids;
  uuids.push_back("00001800-0000-1000-8000-00805f9b34fb");
  uuids.push_back("00001801-0000-1000-8000-00805f9b34fb");
  properties->uuids.ReplaceValue(uuids);

  properties->modalias.ReplaceValue("usb:v05ACp030Dd0306");

  properties_map_[dbus::ObjectPath(kPairedDevicePath)] = properties;
  device_list_.push_back(dbus::ObjectPath(kPairedDevicePath));
}

FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() {
  // Clean up Properties structures
  STLDeleteValues(&properties_map_);
}

void FakeBluetoothDeviceClient::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void FakeBluetoothDeviceClient::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

std::vector<dbus::ObjectPath> FakeBluetoothDeviceClient::GetDevicesForAdapter(
    const dbus::ObjectPath& adapter_path) {
  if (adapter_path ==
      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath))
    return device_list_;
  else
    return std::vector<dbus::ObjectPath>();
}

FakeBluetoothDeviceClient::Properties*
FakeBluetoothDeviceClient::GetProperties(const dbus::ObjectPath& object_path) {
  PropertiesMap::iterator iter = properties_map_.find(object_path);
  if (iter != properties_map_.end())
    return iter->second;
  return NULL;
}

void FakeBluetoothDeviceClient::Connect(
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  VLOG(1) << "Connect: " << object_path.value();
  Properties* properties = GetProperties(object_path);

  if (properties->connected.value() == true) {
    // Already connected.
    callback.Run();
    return;
  }

  if (properties->paired.value() != true &&
      object_path != dbus::ObjectPath(kMicrosoftMousePath)) {
    // Must be paired.
    error_callback.Run(bluetooth_device::kErrorFailed, "Not paired");
    return;
  } else if (properties->paired.value() == true &&
             object_path == dbus::ObjectPath(kUnconnectableDevicePath)) {
    // Must not be paired
    error_callback.Run(bluetooth_device::kErrorFailed,
                       "Connection fails while paired");
    return;
  }

  // The device can be connected.
  properties->connected.ReplaceValue(true);
  callback.Run();

  AddInputDeviceIfNeeded(object_path, properties);
}

void FakeBluetoothDeviceClient::Disconnect(
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  VLOG(1) << "Disconnect: " << object_path.value();
  Properties* properties = GetProperties(object_path);

  if (properties->connected.value() == true) {
    callback.Run();
    properties->connected.ReplaceValue(false);
  } else {
    error_callback.Run("org.bluez.Error.NotConnected", "Not Connected");
  }
}

void FakeBluetoothDeviceClient::ConnectProfile(
    const dbus::ObjectPath& object_path,
    const std::string& uuid,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid;

  FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
      static_cast<FakeBluetoothProfileManagerClient*>(
          DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
  FakeBluetoothProfileServiceProvider* profile_service_provider =
      fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
  if (profile_service_provider == NULL) {
    error_callback.Run(kNoResponseError, "Missing profile");
    return;
  }

  // Make a socket pair of a compatible type with the type used by Bluetooth;
  // spin up a thread to simulate the server side and wrap the client side in
  // a D-Bus file descriptor object.
  int socket_type = SOCK_STREAM;
  if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid)
    socket_type = SOCK_SEQPACKET;

  int fds[2];
  if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) {
    error_callback.Run(kNoResponseError, "socketpair call failed");
    return;
  }

  int args;
  args = fcntl(fds[1], F_GETFL, NULL);
  if (args < 0) {
    error_callback.Run(kNoResponseError, "failed to get socket flags");
    return;
  }

  args |= O_NONBLOCK;
  if (fcntl(fds[1], F_SETFL, args) < 0) {
    error_callback.Run(kNoResponseError, "failed to set socket non-blocking");
    return;
  }

  base::WorkerPool::GetTaskRunner(false)->PostTask(
      FROM_HERE,
      base::Bind(&SimulatedProfileSocket,
                 fds[0]));

  scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1]));

  // Post the new connection to the service provider.
  BluetoothProfileServiceProvider::Delegate::Options options;

  profile_service_provider->NewConnection(
      object_path,
      fd.Pass(),
      options,
      base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback,
                 base::Unretained(this),
                 object_path,
                 callback,
                 error_callback));
}

void FakeBluetoothDeviceClient::DisconnectProfile(
    const dbus::ObjectPath& object_path,
    const std::string& uuid,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid;

  FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
      static_cast<FakeBluetoothProfileManagerClient*>(
          DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
  FakeBluetoothProfileServiceProvider* profile_service_provider =
      fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
  if (profile_service_provider == NULL) {
    error_callback.Run(kNoResponseError, "Missing profile");
    return;
  }

  profile_service_provider->RequestDisconnection(
      object_path,
      base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback,
                 base::Unretained(this),
                 object_path,
                 callback,
                 error_callback));
}

void FakeBluetoothDeviceClient::Pair(
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  VLOG(1) << "Pair: " << object_path.value();
  Properties* properties = GetProperties(object_path);

  if (properties->paired.value() == true) {
    // Already paired.
    callback.Run();
    return;
  }

  pairing_cancelled_ = false;

  FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
      static_cast<FakeBluetoothAgentManagerClient*>(
          DBusThreadManager::Get()->GetBluetoothAgentManagerClient());
  FakeBluetoothAgentServiceProvider* agent_service_provider =
      fake_bluetooth_agent_manager_client->GetAgentServiceProvider();
  if (agent_service_provider == NULL) {
    error_callback.Run(kNoResponseError, "Missing agent");
    return;
  }

  if (object_path == dbus::ObjectPath(kAppleMousePath) ||
      object_path == dbus::ObjectPath(kMicrosoftMousePath) ||
      object_path == dbus::ObjectPath(kUnconnectableDevicePath)) {
    // No need to call anything on the pairing delegate, just wait 3 times
    // the interval before acting as if the other end accepted it.
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
                   base::Unretained(this),
                   object_path, callback, error_callback),
        base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));

  } else if (object_path == dbus::ObjectPath(kAppleKeyboardPath)) {
    // Display a Pincode, and wait 7 times the interval before acting as
    // if the other end accepted it.
    agent_service_provider->DisplayPinCode(object_path, "123456");

    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
                   base::Unretained(this),
                   object_path, callback, error_callback),
        base::TimeDelta::FromMilliseconds(7 * simulation_interval_ms_));

  } else if (object_path == dbus::ObjectPath(kVanishingDevicePath)) {
    // The vanishing device simulates being too far away, and thus times out.
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::TimeoutSimulatedPairing,
                   base::Unretained(this),
                   object_path, error_callback),
        base::TimeDelta::FromMilliseconds(4 * simulation_interval_ms_));

  } else if (object_path == dbus::ObjectPath(kMotorolaKeyboardPath)) {
    // Display a passkey, and each interval act as if another key was entered
    // for it.
    agent_service_provider->DisplayPasskey(object_path, 123456, 0);

    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress,
                   base::Unretained(this),
                   1, object_path, callback, error_callback),
        base::TimeDelta::FromMilliseconds(simulation_interval_ms_));

  } else if (object_path == dbus::ObjectPath(kSonyHeadphonesPath)) {
    // Request a Pincode.
    agent_service_provider->RequestPinCode(
        object_path,
        base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback,
                   base::Unretained(this),
                   object_path,
                   callback,
                   error_callback));

  } else if (object_path == dbus::ObjectPath(kPhonePath)) {
    // Request confirmation of a Passkey.
    agent_service_provider->RequestConfirmation(
        object_path, 123456,
        base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback,
                   base::Unretained(this),
                   object_path,
                   callback,
                   error_callback));

  } else if (object_path == dbus::ObjectPath(kWeirdDevicePath)) {
    // Request a Passkey from the user.
    agent_service_provider->RequestPasskey(
        object_path,
        base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback,
                   base::Unretained(this),
                   object_path,
                   callback,
                   error_callback));

  } else if (object_path == dbus::ObjectPath(kUnpairableDevicePath)) {
    // Fails the pairing with an org.bluez.Error.Failed error.
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing,
                   base::Unretained(this),
                   object_path, error_callback),
        base::TimeDelta::FromMilliseconds(simulation_interval_ms_));

  } else {
    error_callback.Run(kNoResponseError, "No pairing fake");
  }
}

void FakeBluetoothDeviceClient::CancelPairing(
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  VLOG(1) << "CancelPairing: " << object_path.value();
  pairing_cancelled_ = true;
  callback.Run();
}


void FakeBluetoothDeviceClient::BeginDiscoverySimulation(
    const dbus::ObjectPath& adapter_path) {
  VLOG(1) << "starting discovery simulation";

  discovery_simulation_step_ = 1;

  base::MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer,
                 base::Unretained(this)),
      base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
}

void FakeBluetoothDeviceClient::EndDiscoverySimulation(
    const dbus::ObjectPath& adapter_path) {
  VLOG(1) << "stopping discovery simulation";
  discovery_simulation_step_ = 0;
}

void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms) {
  simulation_interval_ms_ = interval_ms;
}

void FakeBluetoothDeviceClient::RemoveDevice(
    const dbus::ObjectPath& adapter_path,
    const dbus::ObjectPath& device_path) {
  std::vector<dbus::ObjectPath>::iterator listiter =
      std::find(device_list_.begin(), device_list_.end(), device_path);
  if (listiter == device_list_.end())
    return;

  PropertiesMap::iterator iter = properties_map_.find(device_path);
  Properties* properties = iter->second;

  VLOG(1) << "removing device: " << properties->alias.value();
  device_list_.erase(listiter);

  // Remove the Input interface if it exists. This should be called before the
  // BluetoothDeviceClient::Observer::DeviceRemoved because it deletes the
  // BluetoothDeviceChromeOS object, including the device_path referenced here.
  FakeBluetoothInputClient* fake_bluetooth_input_client =
      static_cast<FakeBluetoothInputClient*>(
          DBusThreadManager::Get()->GetBluetoothInputClient());
  fake_bluetooth_input_client->RemoveInputDevice(device_path);

  FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                    DeviceRemoved(device_path));

  delete properties;
  properties_map_.erase(iter);
}

void FakeBluetoothDeviceClient::OnPropertyChanged(
    const dbus::ObjectPath& object_path,
    const std::string& property_name) {
  FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                    DevicePropertyChanged(object_path, property_name));
}

void FakeBluetoothDeviceClient::DiscoverySimulationTimer() {
  if (!discovery_simulation_step_)
    return;

  // Timer fires every .75s, the numbers below are arbitrary to give a feel
  // for a discovery process.
  VLOG(1) << "discovery simulation, step " << discovery_simulation_step_;
  if (discovery_simulation_step_ == 2) {
    if (std::find(device_list_.begin(), device_list_.end(),
                  dbus::ObjectPath(kAppleMousePath)) == device_list_.end()) {
      Properties* properties = new Properties(base::Bind(
          &FakeBluetoothDeviceClient::OnPropertyChanged,
          base::Unretained(this),
          dbus::ObjectPath(kAppleMousePath)));
      properties->address.ReplaceValue(kAppleMouseAddress);
      properties->bluetooth_class.ReplaceValue(kAppleMouseClass);
      properties->name.ReplaceValue("Fake Apple Magic Mouse");
      properties->alias.ReplaceValue(kAppleMouseName);
      properties->adapter.ReplaceValue(
          dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));

      std::vector<std::string> uuids;
      uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
      properties->uuids.ReplaceValue(uuids);

      properties_map_[dbus::ObjectPath(kAppleMousePath)] = properties;
      device_list_.push_back(dbus::ObjectPath(kAppleMousePath));
      FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                        DeviceAdded(dbus::ObjectPath(kAppleMousePath)));
    }

  } else if (discovery_simulation_step_ == 4) {
    if (std::find(device_list_.begin(), device_list_.end(),
                  dbus::ObjectPath(kAppleKeyboardPath)) == device_list_.end()) {
      Properties *properties = new Properties(base::Bind(
          &FakeBluetoothDeviceClient::OnPropertyChanged,
          base::Unretained(this),
          dbus::ObjectPath(kAppleKeyboardPath)));
      properties->address.ReplaceValue(kAppleKeyboardAddress);
      properties->bluetooth_class.ReplaceValue(kAppleKeyboardClass);
      properties->name.ReplaceValue("Fake Apple Wireless Keyboard");
      properties->alias.ReplaceValue(kAppleKeyboardName);
      properties->adapter.ReplaceValue(
          dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));

      std::vector<std::string> uuids;
      uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
      properties->uuids.ReplaceValue(uuids);

      properties_map_[dbus::ObjectPath(kAppleKeyboardPath)] = properties;
      device_list_.push_back(dbus::ObjectPath(kAppleKeyboardPath));
      FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                        DeviceAdded(dbus::ObjectPath(kAppleKeyboardPath)));
    }

    if (std::find(device_list_.begin(), device_list_.end(),
                  dbus::ObjectPath(kVanishingDevicePath)) ==
        device_list_.end()) {
      Properties* properties = new Properties(base::Bind(
          &FakeBluetoothDeviceClient::OnPropertyChanged,
          base::Unretained(this),
          dbus::ObjectPath(kVanishingDevicePath)));
      properties->address.ReplaceValue(kVanishingDeviceAddress);
      properties->bluetooth_class.ReplaceValue(kVanishingDeviceClass);
      properties->name.ReplaceValue("Fake Vanishing Device");
      properties->alias.ReplaceValue(kVanishingDeviceName);
      properties->adapter.ReplaceValue(
          dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));

      properties_map_[dbus::ObjectPath(kVanishingDevicePath)] = properties;
      device_list_.push_back(dbus::ObjectPath(kVanishingDevicePath));
      FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                        DeviceAdded(dbus::ObjectPath(kVanishingDevicePath)));
    }

  } else if (discovery_simulation_step_ == 7) {
    if (std::find(device_list_.begin(), device_list_.end(),
                  dbus::ObjectPath(kMicrosoftMousePath)) ==
        device_list_.end()) {
      Properties* properties = new Properties(base::Bind(
          &FakeBluetoothDeviceClient::OnPropertyChanged,
          base::Unretained(this),
          dbus::ObjectPath(kMicrosoftMousePath)));
      properties->address.ReplaceValue(kMicrosoftMouseAddress);
      properties->bluetooth_class.ReplaceValue(kMicrosoftMouseClass);
      properties->name.ReplaceValue("Fake Microsoft Mouse");
      properties->alias.ReplaceValue(kMicrosoftMouseName);
      properties->adapter.ReplaceValue(
          dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));

      std::vector<std::string> uuids;
      uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
      properties->uuids.ReplaceValue(uuids);

      properties_map_[dbus::ObjectPath(kMicrosoftMousePath)] = properties;
      device_list_.push_back(dbus::ObjectPath(kMicrosoftMousePath));
      FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                        DeviceAdded(dbus::ObjectPath(kMicrosoftMousePath)));
    }

  } else if (discovery_simulation_step_ == 8) {
    if (std::find(device_list_.begin(), device_list_.end(),
                  dbus::ObjectPath(kMotorolaKeyboardPath)) ==
        device_list_.end()) {
      Properties* properties = new Properties(base::Bind(
          &FakeBluetoothDeviceClient::OnPropertyChanged,
          base::Unretained(this),
          dbus::ObjectPath(kMotorolaKeyboardPath)));
      properties->address.ReplaceValue(kMotorolaKeyboardAddress);
      properties->bluetooth_class.ReplaceValue(kMotorolaKeyboardClass);
      properties->name.ReplaceValue("Fake Motorola Keyboard");
      properties->alias.ReplaceValue(kMotorolaKeyboardName);
      properties->adapter.ReplaceValue(
          dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));

      std::vector<std::string> uuids;
      uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
      properties->uuids.ReplaceValue(uuids);

      properties_map_[dbus::ObjectPath(kMotorolaKeyboardPath)] = properties;
      device_list_.push_back(dbus::ObjectPath(kMotorolaKeyboardPath));
      FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                        DeviceAdded(dbus::ObjectPath(kMotorolaKeyboardPath)));
    }

    if (std::find(device_list_.begin(), device_list_.end(),
                  dbus::ObjectPath(kSonyHeadphonesPath)) ==
        device_list_.end()) {
      Properties* properties = new Properties(base::Bind(
          &FakeBluetoothDeviceClient::OnPropertyChanged,
          base::Unretained(this),
          dbus::ObjectPath(kSonyHeadphonesPath)));
      properties->address.ReplaceValue(kSonyHeadphonesAddress);
      properties->bluetooth_class.ReplaceValue(kSonyHeadphonesClass);
      properties->name.ReplaceValue("Fake Sony Headphones");
      properties->alias.ReplaceValue(kSonyHeadphonesName);
      properties->adapter.ReplaceValue(
          dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));

      properties_map_[dbus::ObjectPath(kSonyHeadphonesPath)] = properties;
      device_list_.push_back(dbus::ObjectPath(kSonyHeadphonesPath));
      FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                        DeviceAdded(dbus::ObjectPath(kSonyHeadphonesPath)));
    }

  } else if (discovery_simulation_step_ == 10) {
    if (std::find(device_list_.begin(), device_list_.end(),
                  dbus::ObjectPath(kPhonePath)) == device_list_.end()) {
      Properties* properties = new Properties(base::Bind(
          &FakeBluetoothDeviceClient::OnPropertyChanged,
          base::Unretained(this),
          dbus::ObjectPath(kPhonePath)));
      properties->address.ReplaceValue(kPhoneAddress);
      properties->bluetooth_class.ReplaceValue(kPhoneClass);
      properties->name.ReplaceValue("Fake Phone");
      properties->alias.ReplaceValue(kPhoneName);
      properties->adapter.ReplaceValue(
          dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));

      properties_map_[dbus::ObjectPath(kPhonePath)] = properties;
      device_list_.push_back(dbus::ObjectPath(kPhonePath));
      FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                        DeviceAdded(dbus::ObjectPath(kPhonePath)));
    }

    if (std::find(device_list_.begin(), device_list_.end(),
                  dbus::ObjectPath(kWeirdDevicePath)) == device_list_.end()) {
      Properties* properties = new Properties(base::Bind(
          &FakeBluetoothDeviceClient::OnPropertyChanged,
          base::Unretained(this),
          dbus::ObjectPath(kWeirdDevicePath)));
      properties->address.ReplaceValue(kWeirdDeviceAddress);
      properties->bluetooth_class.ReplaceValue(kWeirdDeviceClass);
      properties->name.ReplaceValue("Fake Weird Device");
      properties->alias.ReplaceValue(kWeirdDeviceName);
      properties->adapter.ReplaceValue(
          dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));

      properties_map_[dbus::ObjectPath(kWeirdDevicePath)] = properties;
      device_list_.push_back(dbus::ObjectPath(kWeirdDevicePath));
      FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                        DeviceAdded(dbus::ObjectPath(kWeirdDevicePath)));
    }

    if (std::find(device_list_.begin(), device_list_.end(),
                  dbus::ObjectPath(kUnconnectableDevicePath)) ==
        device_list_.end()) {
      Properties* properties = new Properties(base::Bind(
          &FakeBluetoothDeviceClient::OnPropertyChanged,
          base::Unretained(this),
          dbus::ObjectPath(kUnconnectableDevicePath)));
      properties->address.ReplaceValue(kUnconnectableDeviceAddress);
      properties->bluetooth_class.ReplaceValue(kUnconnectableDeviceClass);
      properties->name.ReplaceValue("Fake Unconnectable Device");
      properties->alias.ReplaceValue(kUnconnectableDeviceName);
      properties->adapter.ReplaceValue(
          dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));

      properties_map_[dbus::ObjectPath(kUnconnectableDevicePath)] = properties;
      device_list_.push_back(dbus::ObjectPath(kUnconnectableDevicePath));
      FOR_EACH_OBSERVER(
          BluetoothDeviceClient::Observer, observers_,
          DeviceAdded(dbus::ObjectPath(kUnconnectableDevicePath)));
    }

    if (std::find(device_list_.begin(), device_list_.end(),
                  dbus::ObjectPath(kUnpairableDevicePath)) ==
        device_list_.end()) {
      Properties* properties = new Properties(base::Bind(
          &FakeBluetoothDeviceClient::OnPropertyChanged,
          base::Unretained(this),
          dbus::ObjectPath(kUnpairableDevicePath)));
      properties->address.ReplaceValue(kUnpairableDeviceAddress);
      properties->bluetooth_class.ReplaceValue(kUnpairableDeviceClass);
      properties->name.ReplaceValue("Fake Unpairable Device");
      properties->alias.ReplaceValue(kUnpairableDeviceName);
      properties->adapter.ReplaceValue(
          dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));

      properties_map_[dbus::ObjectPath(kUnpairableDevicePath)] = properties;
      device_list_.push_back(dbus::ObjectPath(kUnpairableDevicePath));
      FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                        DeviceAdded(dbus::ObjectPath(kUnpairableDevicePath)));
    }

  } else if (discovery_simulation_step_ == 13) {
    RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
                 dbus::ObjectPath(kVanishingDevicePath));

  } else if (discovery_simulation_step_ == 14) {
    return;

  }

  ++discovery_simulation_step_;
  base::MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer,
                 base::Unretained(this)),
      base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
}


void FakeBluetoothDeviceClient::CompleteSimulatedPairing(
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  VLOG(1) << "CompleteSimulatedPairing: " << object_path.value();
  if (pairing_cancelled_) {
    pairing_cancelled_ = false;

    error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled,
                       "Cancaled");
  } else {
    Properties* properties = GetProperties(object_path);

    properties->paired.ReplaceValue(true);
    callback.Run();

    AddInputDeviceIfNeeded(object_path, properties);
  }
}

void FakeBluetoothDeviceClient::TimeoutSimulatedPairing(
    const dbus::ObjectPath& object_path,
    const ErrorCallback& error_callback) {
  VLOG(1) << "TimeoutSimulatedPairing: " << object_path.value();

  error_callback.Run(bluetooth_device::kErrorAuthenticationTimeout,
                     "Timed out");
}

void FakeBluetoothDeviceClient::CancelSimulatedPairing(
    const dbus::ObjectPath& object_path,
    const ErrorCallback& error_callback) {
  VLOG(1) << "CancelSimulatedPairing: " << object_path.value();

  error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled,
                     "Canceled");
}

void FakeBluetoothDeviceClient::RejectSimulatedPairing(
    const dbus::ObjectPath& object_path,
    const ErrorCallback& error_callback) {
  VLOG(1) << "RejectSimulatedPairing: " << object_path.value();

  error_callback.Run(bluetooth_device::kErrorAuthenticationRejected,
                     "Rejected");
}

void FakeBluetoothDeviceClient::FailSimulatedPairing(
    const dbus::ObjectPath& object_path,
    const ErrorCallback& error_callback) {
  VLOG(1) << "FailSimulatedPairing: " << object_path.value();

  error_callback.Run(bluetooth_device::kErrorFailed, "Failed");
}

void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded(
    const dbus::ObjectPath& object_path,
    Properties* properties) {
  // If the paired device is a HID device based on it's bluetooth class,
  // simulate the Input interface.
  FakeBluetoothInputClient* fake_bluetooth_input_client =
      static_cast<FakeBluetoothInputClient*>(
          DBusThreadManager::Get()->GetBluetoothInputClient());

  if ((properties->bluetooth_class.value() & 0x001f03) == 0x000500)
    fake_bluetooth_input_client->AddInputDevice(object_path);
}

void FakeBluetoothDeviceClient::PinCodeCallback(
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback,
    BluetoothAgentServiceProvider::Delegate::Status status,
    const std::string& pincode) {
  VLOG(1) << "PinCodeCallback: " << object_path.value();

  if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
                   base::Unretained(this),
                   object_path, callback, error_callback),
        base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));

  } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
                   base::Unretained(this),
                   object_path, error_callback),
        base::TimeDelta::FromMilliseconds(simulation_interval_ms_));

  } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
                   base::Unretained(this),
                   object_path, error_callback),
        base::TimeDelta::FromMilliseconds(simulation_interval_ms_));

  }
}

void FakeBluetoothDeviceClient::PasskeyCallback(
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback,
    BluetoothAgentServiceProvider::Delegate::Status status,
    uint32 passkey) {
  VLOG(1) << "PasskeyCallback: " << object_path.value();

  if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
                   base::Unretained(this),
                   object_path, callback, error_callback),
        base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));

  } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
                   base::Unretained(this),
                   object_path, error_callback),
        base::TimeDelta::FromMilliseconds(simulation_interval_ms_));

  } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
                   base::Unretained(this),
                   object_path, error_callback),
        base::TimeDelta::FromMilliseconds(simulation_interval_ms_));

  }
}

void FakeBluetoothDeviceClient::ConfirmationCallback(
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback,
    BluetoothAgentServiceProvider::Delegate::Status status) {
  VLOG(1) << "ConfirmationCallback: " << object_path.value();

  if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
                   base::Unretained(this),
                   object_path, callback, error_callback),
        base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));

  } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
                   base::Unretained(this),
                   object_path, error_callback),
        base::TimeDelta::FromMilliseconds(simulation_interval_ms_));

  } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
                   base::Unretained(this),
                   object_path, error_callback),
        base::TimeDelta::FromMilliseconds(simulation_interval_ms_));

  }
}

void FakeBluetoothDeviceClient::SimulateKeypress(
    uint16 entered,
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  VLOG(1) << "SimulateKeypress " << entered << ": " << object_path.value();

  FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
      static_cast<FakeBluetoothAgentManagerClient*>(
          DBusThreadManager::Get()->GetBluetoothAgentManagerClient());
  FakeBluetoothAgentServiceProvider* agent_service_provider =
      fake_bluetooth_agent_manager_client->GetAgentServiceProvider();

  // The agent service provider object could have been destroyed after the
  // pairing is canceled.
  if (!agent_service_provider)
    return;

  agent_service_provider->DisplayPasskey(object_path, 123456, entered);

  if (entered < 7) {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress,
                   base::Unretained(this),
                   entered + 1, object_path, callback, error_callback),
        base::TimeDelta::FromMilliseconds(simulation_interval_ms_));

  } else {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
                   base::Unretained(this),
                   object_path, callback, error_callback),
        base::TimeDelta::FromMilliseconds(simulation_interval_ms_));

  }
}

void FakeBluetoothDeviceClient::ConnectionCallback(
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback,
    BluetoothProfileServiceProvider::Delegate::Status status) {
  VLOG(1) << "ConnectionCallback: " << object_path.value();

  if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) {
    callback.Run();
  } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) {
    // TODO(keybuk): tear down this side of the connection
    error_callback.Run(bluetooth_device::kErrorFailed, "Canceled");
  } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) {
    // TODO(keybuk): tear down this side of the connection
    error_callback.Run(bluetooth_device::kErrorFailed, "Rejected");
  }
}

void FakeBluetoothDeviceClient::DisconnectionCallback(
    const dbus::ObjectPath& object_path,
    const base::Closure& callback,
    const ErrorCallback& error_callback,
    BluetoothProfileServiceProvider::Delegate::Status status) {
  VLOG(1) << "DisconnectionCallback: " << object_path.value();

  if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) {
    // TODO(keybuk): tear down this side of the connection
    callback.Run();
  } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) {
    error_callback.Run(bluetooth_device::kErrorFailed, "Canceled");
  } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) {
    error_callback.Run(bluetooth_device::kErrorFailed, "Rejected");
  }
}

}  // namespace chromeos
