//
//  Copyright 2015 Google, Inc.
//
//  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.
//

#include "service/daemon.h"

#include <memory>

#include <base/logging.h>
#include <base/run_loop.h>

#include "abstract_message_loop.h"
#include "service/adapter.h"
#include "service/hal/bluetooth_av_interface.h"
#include "service/hal/bluetooth_avrcp_interface.h"
#include "service/hal/bluetooth_gatt_interface.h"
#include "service/hal/bluetooth_interface.h"
#include "service/ipc/ipc_manager.h"
#include "service/settings.h"
#include "service/switches.h"

namespace bluetooth {

namespace {

// The global Daemon instance.
Daemon* g_daemon = nullptr;

class DaemonImpl : public Daemon, public ipc::IPCManager::Delegate {
 public:
  DaemonImpl() : initialized_(false) {}

  ~DaemonImpl() override {
    if (!initialized_) return;

    CleanUpBluetoothStack();
  }

  void StartMainLoop() override { base::RunLoop().Run(); }

  Settings* GetSettings() const override { return settings_.get(); }

  btbase::AbstractMessageLoop* GetMessageLoop() const override {
    return message_loop_.get();
  }

 private:
  // ipc::IPCManager::Delegate implementation:
  void OnIPCHandlerStarted(ipc::IPCManager::Type /* type */) override {
    if (!settings_->EnableOnStart()) return;
    adapter_->Enable();
  }

  void OnIPCHandlerStopped(ipc::IPCManager::Type /* type */) override {
    // Do nothing.
  }

  bool StartUpBluetoothInterfaces() {
    if (!hal::BluetoothInterface::Initialize()) goto failed;

    if (!hal::BluetoothGattInterface::Initialize()) goto failed;

    if (!hal::BluetoothAvInterface::Initialize()) goto failed;

    if (!hal::BluetoothAvrcpInterface::Initialize()) goto failed;

    return true;

  failed:
    ShutDownBluetoothInterfaces();
    return false;
  }

  void ShutDownBluetoothInterfaces() {
    if (hal::BluetoothGattInterface::IsInitialized())
      hal::BluetoothGattInterface::CleanUp();
    if (hal::BluetoothInterface::IsInitialized())
      hal::BluetoothInterface::CleanUp();
    if (hal::BluetoothAvInterface::IsInitialized())
      hal::BluetoothAvInterface::CleanUp();
    if (hal::BluetoothAvrcpInterface::IsInitialized())
      hal::BluetoothAvrcpInterface::CleanUp();
  }

  void CleanUpBluetoothStack() {
    // The Adapter object needs to be cleaned up before the HAL interfaces.
    ipc_manager_.reset();
    adapter_.reset();
    ShutDownBluetoothInterfaces();
  }

  bool SetUpIPC() {
    // If an IPC socket path was given, initialize IPC with it. Otherwise
    // initialize Binder IPC.
    if (settings_->UseSocketIPC()) {
      if (!ipc_manager_->Start(ipc::IPCManager::TYPE_LINUX, this)) {
        LOG(ERROR) << "Failed to set up UNIX domain-socket IPCManager";
        return false;
      }
      return true;
    }

#if !defined(OS_GENERIC)
    if (!ipc_manager_->Start(ipc::IPCManager::TYPE_BINDER, this)) {
      LOG(ERROR) << "Failed to set up Binder IPCManager";
      return false;
    }
#else
    if (!ipc_manager_->Start(ipc::IPCManager::TYPE_DBUS, this)) {
      LOG(ERROR) << "Failed to set up DBus IPCManager";
      return false;
    }
#endif

    return true;
  }

  bool Init() override {
    CHECK(!initialized_);
    message_loop_.reset(new btbase::AbstractMessageLoop());

    settings_.reset(new Settings());
    if (!settings_->Init()) {
      LOG(ERROR) << "Failed to set up Settings";
      return false;
    }

    if (!StartUpBluetoothInterfaces()) {
      LOG(ERROR) << "Failed to set up HAL Bluetooth interfaces";
      return false;
    }

    adapter_ = Adapter::Create();
    ipc_manager_.reset(new ipc::IPCManager(adapter_.get()));

    if (!SetUpIPC()) {
      CleanUpBluetoothStack();
      return false;
    }

    initialized_ = true;
    LOG(INFO) << "Daemon initialized";

    return true;
  }

  bool initialized_;
  std::unique_ptr<btbase::AbstractMessageLoop> message_loop_;
  std::unique_ptr<Settings> settings_;
  std::unique_ptr<Adapter> adapter_;
  std::unique_ptr<ipc::IPCManager> ipc_manager_;

  DISALLOW_COPY_AND_ASSIGN(DaemonImpl);
};

}  // namespace

// static
bool Daemon::Initialize() {
  CHECK(!g_daemon);

  g_daemon = new DaemonImpl();
  if (g_daemon->Init()) return true;

  LOG(ERROR) << "Failed to initialize the Daemon object";

  delete g_daemon;
  g_daemon = nullptr;

  return false;
}

// static
void Daemon::ShutDown() {
  CHECK(g_daemon);
  delete g_daemon;
  g_daemon = nullptr;
}

// static
void Daemon::InitializeForTesting(Daemon* test_daemon) {
  CHECK(test_daemon);
  CHECK(!g_daemon);

  g_daemon = test_daemon;
}

// static
Daemon* Daemon::Get() {
  CHECK(g_daemon);
  return g_daemon;
}

}  // namespace bluetooth
