// Copyright (c) 2012 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 "chrome/browser/extensions/api/bluetooth/bluetooth_api.h"

#include <string>

#include "base/memory/ref_counted.h"
#include "chrome/browser/extensions/api/bluetooth/bluetooth_api_factory.h"
#include "chrome/browser/extensions/api/bluetooth/bluetooth_api_utils.h"
#include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h"
#include "chrome/browser/extensions/event_names.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/bluetooth.h"
#include "chrome/common/extensions/permissions/bluetooth_permission.h"
#include "content/public/browser/browser_thread.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
#include "device/bluetooth/bluetooth_profile.h"
#include "device/bluetooth/bluetooth_service_record.h"
#include "device/bluetooth/bluetooth_socket.h"
#include "device/bluetooth/bluetooth_utils.h"
#include "extensions/browser/event_router.h"
#include "extensions/common/permissions/permissions_data.h"
#include "net/base/io_buffer.h"

using device::BluetoothAdapter;
using device::BluetoothDevice;
using device::BluetoothProfile;
using device::BluetoothServiceRecord;
using device::BluetoothSocket;

namespace {

extensions::ExtensionBluetoothEventRouter* GetEventRouter(Profile* profile) {
  return extensions::BluetoothAPI::Get(profile)->bluetooth_event_router();
}

}  // namespace

namespace {

const char kCouldNotGetLocalOutOfBandPairingData[] =
    "Could not get local Out Of Band Pairing Data";
const char kCouldNotSetOutOfBandPairingData[] =
    "Could not set Out Of Band Pairing Data";
const char kFailedToConnect[] = "Connection failed";
const char kInvalidDevice[] = "Invalid device";
const char kInvalidUuid[] = "Invalid UUID";
const char kPermissionDenied[] = "Permission to add profile denied.";
const char kProfileAlreadyRegistered[] =
    "This profile has already been registered";
const char kProfileNotFound[] = "Profile not found: invalid uuid";
const char kProfileRegistrationFailed[] = "Profile registration failed";
const char kServiceDiscoveryFailed[] = "Service discovery failed";
const char kSocketNotFoundError[] = "Socket not found: invalid socket id";
const char kStartDiscoveryFailed[] = "Starting discovery failed";
const char kStopDiscoveryFailed[] = "Failed to stop discovery";

}  // namespace

namespace AddProfile = extensions::api::bluetooth::AddProfile;
namespace bluetooth = extensions::api::bluetooth;
namespace Connect = extensions::api::bluetooth::Connect;
namespace Disconnect = extensions::api::bluetooth::Disconnect;
namespace GetDevices = extensions::api::bluetooth::GetDevices;
namespace GetProfiles = extensions::api::bluetooth::GetProfiles;
namespace GetServices = extensions::api::bluetooth::GetServices;
namespace Read = extensions::api::bluetooth::Read;
namespace RemoveProfile = extensions::api::bluetooth::RemoveProfile;
namespace SetOutOfBandPairingData =
    extensions::api::bluetooth::SetOutOfBandPairingData;
namespace Write = extensions::api::bluetooth::Write;

namespace extensions {

// static
BluetoothAPI* BluetoothAPI::Get(Profile* profile) {
  return BluetoothAPIFactory::GetForProfile(profile);
}

BluetoothAPI::BluetoothAPI(Profile* profile) : profile_(profile) {
  ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
      this, bluetooth::OnAdapterStateChanged::kEventName);
}

BluetoothAPI::~BluetoothAPI() {
}

ExtensionBluetoothEventRouter* BluetoothAPI::bluetooth_event_router() {
  if (!bluetooth_event_router_)
    bluetooth_event_router_.reset(new ExtensionBluetoothEventRouter(profile_));

  return bluetooth_event_router_.get();
}

void BluetoothAPI::Shutdown() {
  ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
}

void BluetoothAPI::OnListenerAdded(const EventListenerInfo& details) {
  if (bluetooth_event_router()->IsBluetoothSupported())
    bluetooth_event_router()->OnListenerAdded();
}

void BluetoothAPI::OnListenerRemoved(const EventListenerInfo& details) {
  if (bluetooth_event_router()->IsBluetoothSupported())
    bluetooth_event_router()->OnListenerRemoved();
}

namespace api {

BluetoothAddProfileFunction::BluetoothAddProfileFunction() {
}

bool BluetoothAddProfileFunction::RunImpl() {
  scoped_ptr<AddProfile::Params> params(AddProfile::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);

  if (!BluetoothDevice::IsUUIDValid(params->profile.uuid)) {
    SetError(kInvalidUuid);
    return false;
  }

  BluetoothPermission::CheckParam param(params->profile.uuid);
  if (!PermissionsData::CheckAPIPermissionWithParam(
          GetExtension(), APIPermission::kBluetooth, &param)) {
    SetError(kPermissionDenied);
    return false;
  }

  uuid_ = device::bluetooth_utils::CanonicalUuid(params->profile.uuid);

  if (GetEventRouter(GetProfile())->HasProfile(uuid_)) {
    SetError(kProfileAlreadyRegistered);
    return false;
  }

  BluetoothProfile::Options options;
  if (params->profile.name.get())
    options.name = *params->profile.name.get();
  if (params->profile.channel.get())
    options.channel = *params->profile.channel.get();
  if (params->profile.psm.get())
    options.psm = *params->profile.psm.get();
  if (params->profile.require_authentication.get()) {
    options.require_authentication =
        *params->profile.require_authentication.get();
  }
  if (params->profile.require_authorization.get()) {
    options.require_authorization =
        *params->profile.require_authorization.get();
  }
  if (params->profile.auto_connect.get())
    options.auto_connect = *params->profile.auto_connect.get();
  if (params->profile.version.get())
    options.version = *params->profile.version.get();
  if (params->profile.features.get())
    options.features = *params->profile.features.get();

  RegisterProfile(
      options,
      base::Bind(&BluetoothAddProfileFunction::OnProfileRegistered, this));

  return true;
}

void BluetoothAddProfileFunction::RegisterProfile(
    const BluetoothProfile::Options& options,
    const BluetoothProfile::ProfileCallback& callback) {
  BluetoothProfile::Register(uuid_, options, callback);
}

void BluetoothAddProfileFunction::OnProfileRegistered(
    BluetoothProfile* bluetooth_profile) {
  if (!bluetooth_profile) {
    SetError(kProfileRegistrationFailed);
    SendResponse(false);
    return;
  }

  if (GetEventRouter(GetProfile())->HasProfile(uuid_)) {
    bluetooth_profile->Unregister();
    SetError(kProfileAlreadyRegistered);
    SendResponse(false);
    return;
  }

  bluetooth_profile->SetConnectionCallback(
      base::Bind(&ExtensionBluetoothEventRouter::DispatchConnectionEvent,
                 base::Unretained(GetEventRouter(GetProfile())),
                 extension_id(),
                 uuid_));
  GetEventRouter(GetProfile())->AddProfile(uuid_, bluetooth_profile);
  SendResponse(true);
}

bool BluetoothRemoveProfileFunction::RunImpl() {
  scoped_ptr<RemoveProfile::Params> params(
      RemoveProfile::Params::Create(*args_));

  if (!BluetoothDevice::IsUUIDValid(params->profile.uuid)) {
    SetError(kInvalidUuid);
    return false;
  }

  std::string uuid =
      device::bluetooth_utils::CanonicalUuid(params->profile.uuid);

  if (!GetEventRouter(GetProfile())->HasProfile(uuid)) {
    SetError(kProfileNotFound);
    return false;
  }

  GetEventRouter(GetProfile())->RemoveProfile(uuid);
  return true;
}

// TODO(youngki): Implement.
bool BluetoothGetProfilesFunction::DoWork(
    scoped_refptr<device::BluetoothAdapter> adapter) {
  scoped_ptr<GetProfiles::Params> params(GetProfiles::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
  const bluetooth::GetProfilesOptions& options = params->options;

  BluetoothDevice* device = adapter->GetDevice(options.device.address);
  if (!device) {
    SetError(kInvalidDevice);
    SendResponse(false);
    return false;
  }

  BluetoothDevice::ServiceList service_list = device->GetServices();

  base::ListValue* profiles = new base::ListValue;
  for (BluetoothDevice::ServiceList::const_iterator iter = service_list.begin();
       iter != service_list.end();
       ++iter) {
    bluetooth::Profile api_profile;
    api_profile.uuid = *iter;
    profiles->Append(api_profile.ToValue().release());
  }

  SetResult(profiles);
  SendResponse(true);

  return true;
}

bool BluetoothGetAdapterStateFunction::DoWork(
    scoped_refptr<BluetoothAdapter> adapter) {
  bluetooth::AdapterState state;
  PopulateAdapterState(*adapter.get(), &state);
  SetResult(state.ToValue().release());
  SendResponse(true);
  return true;
}

BluetoothGetDevicesFunction::BluetoothGetDevicesFunction()
    : device_events_sent_(0) {}

void BluetoothGetDevicesFunction::DispatchDeviceSearchResult(
    const BluetoothDevice& device) {
  bluetooth::Device extension_device;
  bluetooth::BluetoothDeviceToApiDevice(device, &extension_device);
  GetEventRouter(GetProfile())->DispatchDeviceEvent(
      extensions::event_names::kBluetoothOnDeviceSearchResult,
      extension_device);

  device_events_sent_++;
}

void BluetoothGetDevicesFunction::FinishDeviceSearch() {
  scoped_ptr<base::ListValue> args(new base::ListValue());
  scoped_ptr<base::DictionaryValue> info(new base::DictionaryValue());
  info->SetInteger("expectedEventCount", device_events_sent_);
  args->Append(info.release());

  scoped_ptr<extensions::Event> event(new extensions::Event(
      extensions::event_names::kBluetoothOnDeviceSearchFinished, args.Pass()));
  extensions::ExtensionSystem::Get(GetProfile())
      ->event_router()
      ->BroadcastEvent(event.Pass());

  SendResponse(true);
}

bool BluetoothGetDevicesFunction::DoWork(
    scoped_refptr<BluetoothAdapter> adapter) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  scoped_ptr<GetDevices::Params> params(GetDevices::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
  const bluetooth::GetDevicesOptions& options = params->options;

  std::string uuid;
  if (options.profile.get() != NULL) {
    uuid = options.profile->uuid;
    if (!BluetoothDevice::IsUUIDValid(uuid)) {
      SetError(kInvalidUuid);
      SendResponse(false);
      return false;
    }
  }

  BluetoothAdapter::DeviceList devices = adapter->GetDevices();
  for (BluetoothAdapter::DeviceList::const_iterator iter = devices.begin();
       iter != devices.end();
       ++iter) {
    const BluetoothDevice* device = *iter;
    DCHECK(device);
    if (uuid.empty() || device->ProvidesServiceWithUUID(uuid))
      DispatchDeviceSearchResult(*device);
  }

  FinishDeviceSearch();

  return true;
}

void BluetoothGetServicesFunction::GetServiceRecordsCallback(
    base::ListValue* services,
    const BluetoothDevice::ServiceRecordList& records) {
  for (BluetoothDevice::ServiceRecordList::const_iterator i = records.begin();
      i != records.end(); ++i) {
    const BluetoothServiceRecord& record = **i;
    bluetooth::ServiceRecord api_record;
    api_record.name = record.name();
    if (!record.uuid().empty())
      api_record.uuid.reset(new std::string(record.uuid()));
    services->Append(api_record.ToValue().release());
  }

  SendResponse(true);
}

void BluetoothGetServicesFunction::OnErrorCallback() {
  SetError(kServiceDiscoveryFailed);
  SendResponse(false);
}

bool BluetoothGetServicesFunction::DoWork(
    scoped_refptr<BluetoothAdapter> adapter) {
  scoped_ptr<GetServices::Params> params(GetServices::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
  const bluetooth::GetServicesOptions& options = params->options;

  BluetoothDevice* device = adapter->GetDevice(options.device_address);
  if (!device) {
    SetError(kInvalidDevice);
    SendResponse(false);
    return false;
  }

  base::ListValue* services = new base::ListValue;
  SetResult(services);

  device->GetServiceRecords(
      base::Bind(&BluetoothGetServicesFunction::GetServiceRecordsCallback,
                 this,
                 services),
      base::Bind(&BluetoothGetServicesFunction::OnErrorCallback,
                 this));

  return true;
}

void BluetoothConnectFunction::OnSuccessCallback() {
  SendResponse(true);
}

void BluetoothConnectFunction::OnErrorCallback() {
  SetError(kFailedToConnect);
  SendResponse(false);
}

bool BluetoothConnectFunction::DoWork(scoped_refptr<BluetoothAdapter> adapter) {
  scoped_ptr<Connect::Params> params(Connect::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
  const bluetooth::ConnectOptions& options = params->options;

  if (!BluetoothDevice::IsUUIDValid(options.profile.uuid)) {
    SetError(kInvalidUuid);
    SendResponse(false);
    return false;
  }

  BluetoothDevice* device = adapter->GetDevice(options.device.address);
  if (!device) {
    SetError(kInvalidDevice);
    SendResponse(false);
    return false;
  }

  std::string uuid = device::bluetooth_utils::CanonicalUuid(
      options.profile.uuid);

  BluetoothProfile* bluetooth_profile =
      GetEventRouter(GetProfile())->GetProfile(uuid);
  if (!bluetooth_profile) {
    SetError(kProfileNotFound);
    SendResponse(false);
    return false;
  }

  device->ConnectToProfile(
      bluetooth_profile,
      base::Bind(&BluetoothConnectFunction::OnSuccessCallback, this),
      base::Bind(&BluetoothConnectFunction::OnErrorCallback, this));

  return true;
}

bool BluetoothDisconnectFunction::RunImpl() {
  scoped_ptr<Disconnect::Params> params(Disconnect::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
  const bluetooth::DisconnectOptions& options = params->options;
  return GetEventRouter(GetProfile())->ReleaseSocket(options.socket.id);
}

BluetoothReadFunction::BluetoothReadFunction() : success_(false) {}
BluetoothReadFunction::~BluetoothReadFunction() {}

bool BluetoothReadFunction::Prepare() {
  scoped_ptr<Read::Params> params(Read::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
  const bluetooth::ReadOptions& options = params->options;

  socket_ = GetEventRouter(GetProfile())->GetSocket(options.socket.id);
  if (socket_.get() == NULL) {
    SetError(kSocketNotFoundError);
    return false;
  }

  success_ = false;
  return true;
}

void BluetoothReadFunction::Work() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

  if (!socket_.get())
    return;

  scoped_refptr<net::GrowableIOBuffer> buffer(new net::GrowableIOBuffer);
  success_ = socket_->Receive(buffer.get());
  if (success_)
    SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer->StartOfBuffer(),
                                                        buffer->offset()));
  else
    SetError(socket_->GetLastErrorMessage());
}

bool BluetoothReadFunction::Respond() {
  return success_;
}

BluetoothWriteFunction::BluetoothWriteFunction()
    : success_(false),
      data_to_write_(NULL) {
}

BluetoothWriteFunction::~BluetoothWriteFunction() {}

bool BluetoothWriteFunction::Prepare() {
  // TODO(bryeung): update to new-style parameter passing when ArrayBuffer
  // support is added
  base::DictionaryValue* options;
  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options));

  base::DictionaryValue* socket;
  EXTENSION_FUNCTION_VALIDATE(options->GetDictionary("socket", &socket));

  int socket_id;
  EXTENSION_FUNCTION_VALIDATE(socket->GetInteger("id", &socket_id));

  socket_ = GetEventRouter(GetProfile())->GetSocket(socket_id);
  if (socket_.get() == NULL) {
    SetError(kSocketNotFoundError);
    return false;
  }

  base::BinaryValue* tmp_data;
  EXTENSION_FUNCTION_VALIDATE(options->GetBinary("data", &tmp_data));
  data_to_write_ = tmp_data;

  success_ = false;
  return socket_.get() != NULL;
}

void BluetoothWriteFunction::Work() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

  if (socket_.get() == NULL)
    return;

  scoped_refptr<net::WrappedIOBuffer> wrapped_io_buffer(
      new net::WrappedIOBuffer(data_to_write_->GetBuffer()));
  scoped_refptr<net::DrainableIOBuffer> drainable_io_buffer(
      new net::DrainableIOBuffer(wrapped_io_buffer.get(),
                                 data_to_write_->GetSize()));
  success_ = socket_->Send(drainable_io_buffer.get());
  if (success_) {
    if (drainable_io_buffer->BytesConsumed() > 0)
      SetResult(new base::FundamentalValue(
          drainable_io_buffer->BytesConsumed()));
    else
      results_.reset();
  } else {
    SetError(socket_->GetLastErrorMessage());
  }
}

bool BluetoothWriteFunction::Respond() {
  return success_;
}

void BluetoothSetOutOfBandPairingDataFunction::OnSuccessCallback() {
  SendResponse(true);
}

void BluetoothSetOutOfBandPairingDataFunction::OnErrorCallback() {
  SetError(kCouldNotSetOutOfBandPairingData);
  SendResponse(false);
}

bool BluetoothSetOutOfBandPairingDataFunction::DoWork(
    scoped_refptr<BluetoothAdapter> adapter) {
  // TODO(bryeung): update to new-style parameter passing when ArrayBuffer
  // support is added
  base::DictionaryValue* options;
  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options));
  std::string address;
  EXTENSION_FUNCTION_VALIDATE(options->GetString("deviceAddress", &address));

  BluetoothDevice* device = adapter->GetDevice(address);
  if (!device) {
    SetError(kInvalidDevice);
    SendResponse(false);
    return false;
  }

  if (options->HasKey("data")) {
    base::DictionaryValue* data_in;
    EXTENSION_FUNCTION_VALIDATE(options->GetDictionary("data", &data_in));

    device::BluetoothOutOfBandPairingData data_out;

    base::BinaryValue* tmp_data;
    EXTENSION_FUNCTION_VALIDATE(data_in->GetBinary("hash", &tmp_data));
    EXTENSION_FUNCTION_VALIDATE(
        tmp_data->GetSize() == device::kBluetoothOutOfBandPairingDataSize);
    memcpy(data_out.hash,
        reinterpret_cast<uint8_t*>(tmp_data->GetBuffer()),
        device::kBluetoothOutOfBandPairingDataSize);

    EXTENSION_FUNCTION_VALIDATE(data_in->GetBinary("randomizer", &tmp_data));
    EXTENSION_FUNCTION_VALIDATE(
        tmp_data->GetSize() == device::kBluetoothOutOfBandPairingDataSize);
    memcpy(data_out.randomizer,
        reinterpret_cast<uint8_t*>(tmp_data->GetBuffer()),
        device::kBluetoothOutOfBandPairingDataSize);

    device->SetOutOfBandPairingData(
        data_out,
        base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnSuccessCallback,
            this),
        base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnErrorCallback,
            this));
  } else {
    device->ClearOutOfBandPairingData(
        base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnSuccessCallback,
            this),
        base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnErrorCallback,
            this));
  }

  return true;
}

void BluetoothGetLocalOutOfBandPairingDataFunction::ReadCallback(
    const device::BluetoothOutOfBandPairingData& data) {
  base::BinaryValue* hash = base::BinaryValue::CreateWithCopiedBuffer(
      reinterpret_cast<const char*>(data.hash),
      device::kBluetoothOutOfBandPairingDataSize);
  base::BinaryValue* randomizer = base::BinaryValue::CreateWithCopiedBuffer(
      reinterpret_cast<const char*>(data.randomizer),
      device::kBluetoothOutOfBandPairingDataSize);

  // TODO(bryeung): convert to bluetooth::OutOfBandPairingData
  // when ArrayBuffer support within objects is completed.
  base::DictionaryValue* result = new base::DictionaryValue();
  result->Set("hash", hash);
  result->Set("randomizer", randomizer);

  SetResult(result);

  SendResponse(true);
}

void BluetoothGetLocalOutOfBandPairingDataFunction::ErrorCallback() {
  SetError(kCouldNotGetLocalOutOfBandPairingData);
  SendResponse(false);
}

bool BluetoothGetLocalOutOfBandPairingDataFunction::DoWork(
    scoped_refptr<BluetoothAdapter> adapter) {
  adapter->ReadLocalOutOfBandPairingData(
      base::Bind(&BluetoothGetLocalOutOfBandPairingDataFunction::ReadCallback,
          this),
      base::Bind(&BluetoothGetLocalOutOfBandPairingDataFunction::ErrorCallback,
          this));

  return true;
}

void BluetoothStartDiscoveryFunction::OnSuccessCallback() {
  SendResponse(true);
}

void BluetoothStartDiscoveryFunction::OnErrorCallback() {
  SetError(kStartDiscoveryFailed);
  GetEventRouter(GetProfile())->SetResponsibleForDiscovery(false);
  SendResponse(false);
  GetEventRouter(GetProfile())->OnListenerRemoved();
}

bool BluetoothStartDiscoveryFunction::DoWork(
    scoped_refptr<BluetoothAdapter> adapter) {
  GetEventRouter(GetProfile())->SetSendDiscoveryEvents(true);

  // If this profile is already discovering devices, there should be nothing
  // else to do.
  if (!GetEventRouter(GetProfile())->IsResponsibleForDiscovery()) {
    GetEventRouter(GetProfile())->SetResponsibleForDiscovery(true);
    GetEventRouter(GetProfile())->OnListenerAdded();
    adapter->StartDiscovering(
        base::Bind(&BluetoothStartDiscoveryFunction::OnSuccessCallback, this),
        base::Bind(&BluetoothStartDiscoveryFunction::OnErrorCallback, this));
  }

  return true;
}

void BluetoothStopDiscoveryFunction::OnSuccessCallback() {
  SendResponse(true);
  GetEventRouter(GetProfile())->OnListenerRemoved();
}

void BluetoothStopDiscoveryFunction::OnErrorCallback() {
  SetError(kStopDiscoveryFailed);
  GetEventRouter(GetProfile())->SetResponsibleForDiscovery(true);
  SendResponse(false);
  GetEventRouter(GetProfile())->OnListenerRemoved();
}

bool BluetoothStopDiscoveryFunction::DoWork(
    scoped_refptr<BluetoothAdapter> adapter) {
  GetEventRouter(GetProfile())->SetSendDiscoveryEvents(false);
  if (GetEventRouter(GetProfile())->IsResponsibleForDiscovery()) {
    adapter->StopDiscovering(
        base::Bind(&BluetoothStopDiscoveryFunction::OnSuccessCallback, this),
        base::Bind(&BluetoothStopDiscoveryFunction::OnErrorCallback, this));
  }

  return true;
}

}  // namespace api
}  // namespace extensions
