// Copyright 2014 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 "components/proximity_auth/bluetooth_connection_finder.h"

#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "components/proximity_auth/bluetooth_connection.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"

using device::BluetoothAdapter;

namespace proximity_auth {

BluetoothConnectionFinder::BluetoothConnectionFinder(
    const RemoteDevice& remote_device,
    const device::BluetoothUUID& uuid,
    const base::TimeDelta& polling_interval)
    : remote_device_(remote_device),
      uuid_(uuid),
      polling_interval_(polling_interval),
      has_delayed_poll_scheduled_(false),
      weak_ptr_factory_(this) {
}

BluetoothConnectionFinder::~BluetoothConnectionFinder() {
  UnregisterAsObserver();
}

void BluetoothConnectionFinder::Find(
    const ConnectionCallback& connection_callback) {
  if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
    VLOG(1) << "[BCF] Bluetooth is unsupported on this platform. Aborting.";
    return;
  }

  DCHECK(start_time_.is_null());
  VLOG(1) << "[BCF] Finding Bluetooth connection...";

  start_time_ = base::TimeTicks::Now();
  connection_callback_ = connection_callback;

  device::BluetoothAdapterFactory::GetAdapter(
      base::Bind(&BluetoothConnectionFinder::OnAdapterInitialized,
                 weak_ptr_factory_.GetWeakPtr()));
}

scoped_ptr<Connection> BluetoothConnectionFinder::CreateConnection() {
  return scoped_ptr<Connection>(new BluetoothConnection(remote_device_, uuid_));
}

bool BluetoothConnectionFinder::IsReadyToPoll() {
  bool is_adapter_available =
      adapter_.get() && adapter_->IsPresent() && adapter_->IsPowered();
  VLOG(1) << "[BCF] Readiness: adapter="
          << (is_adapter_available ? "available" : "unavailable");
  return is_adapter_available;
}

void BluetoothConnectionFinder::PollIfReady() {
  if (!IsReadyToPoll())
    return;

  // If there is a pending task to poll at a later time, the time requisite
  // timeout has not yet elapsed since the previous polling attempt. In that
  // case, keep waiting until the delayed task comes in.
  if (has_delayed_poll_scheduled_)
    return;

  // If the |connection_| exists, wait for it to connect or fail prior to
  // polling again.
  if (connection_)
    return;

  VLOG(1) << "[BCF] Polling for connection...";
  connection_ = CreateConnection();
  connection_->AddObserver(this);
  connection_->Connect();
}

void BluetoothConnectionFinder::DelayedPollIfReady() {
  // Note that there is no longer a pending task, and therefore polling is
  // permitted.
  has_delayed_poll_scheduled_ = false;
  PollIfReady();
}

void BluetoothConnectionFinder::UnregisterAsObserver() {
  if (connection_) {
    connection_->RemoveObserver(this);
    // The connection is about to be released or destroyed, so no need to clear
    // it explicitly here.
  }

  if (adapter_.get()) {
    adapter_->RemoveObserver(this);
    adapter_ = NULL;
  }
}

void BluetoothConnectionFinder::OnAdapterInitialized(
    scoped_refptr<BluetoothAdapter> adapter) {
  adapter_ = adapter;
  adapter_->AddObserver(this);
  PollIfReady();
}

void BluetoothConnectionFinder::AdapterPresentChanged(BluetoothAdapter* adapter,
                                                      bool present) {
  PollIfReady();
}

void BluetoothConnectionFinder::AdapterPoweredChanged(BluetoothAdapter* adapter,
                                                      bool powered) {
  PollIfReady();
}

void BluetoothConnectionFinder::OnConnectionStatusChanged(
    const Connection& connection,
    Connection::Status old_status,
    Connection::Status new_status) {
  DCHECK_EQ(&connection, connection_.get());

  if (connection_->IsConnected()) {
    base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
    VLOG(1) << "[BCF] Connection found! Elapsed Time: "
            << elapsed.InMilliseconds() << "ms.";
    UnregisterAsObserver();
    connection_callback_.Run(connection_.Pass());
  } else if (old_status == Connection::IN_PROGRESS) {
    VLOG(1) << "[BCF] Connection failed! Scheduling another polling iteration.";
    connection_.reset();
    has_delayed_poll_scheduled_ = true;
    base::MessageLoopProxy::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&BluetoothConnectionFinder::DelayedPollIfReady,
                   weak_ptr_factory_.GetWeakPtr()),
        polling_interval_);
  }
}

}  // namespace proximity_auth
