//
//  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_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(false /* start_restricted */);
  }

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

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

    if (!hal::BluetoothGattInterface::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();
  }

  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
