//
//  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 "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(); }

  base::MessageLoop* 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 base::MessageLoop());

    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<base::MessageLoop> 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
