/*
 * Copyright 2019 The Android Open Source Project
 *
 * 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.
 */
#define LOG_TAG "BtGdModule"

#include "module.h"
#include "common/init_flags.h"
#include "dumpsys/init_flags.h"
#include "os/wakelock_manager.h"

using ::bluetooth::os::Handler;
using ::bluetooth::os::Thread;
using ::bluetooth::os::WakelockManager;

namespace bluetooth {

constexpr std::chrono::milliseconds kModuleStopTimeout = std::chrono::milliseconds(2000);

ModuleFactory::ModuleFactory(std::function<Module*()> ctor) : ctor_(ctor) {
}

Handler* Module::GetHandler() const {
  ASSERT_LOG(handler_ != nullptr, "Can't get handler when it's not started");
  return handler_;
}

DumpsysDataFinisher EmptyDumpsysDataFinisher = [](DumpsysDataBuilder* dumpsys_data_builder) {};
DumpsysDataFinisher Module::GetDumpsysData(flatbuffers::FlatBufferBuilder* builder) const {
  return EmptyDumpsysDataFinisher;
}

const ModuleRegistry* Module::GetModuleRegistry() const {
  return registry_;
}

Module* Module::GetDependency(const ModuleFactory* module) const {
  for (auto& dependency : dependencies_.list_) {
    if (dependency == module) {
      return registry_->Get(module);
    }
  }

  ASSERT_LOG(false, "Module was not listed as a dependency in ListDependencies");
}

Module* ModuleRegistry::Get(const ModuleFactory* module) const {
  auto instance = started_modules_.find(module);
  ASSERT(instance != started_modules_.end());
  return instance->second;
}

bool ModuleRegistry::IsStarted(const ModuleFactory* module) const {
  return started_modules_.find(module) != started_modules_.end();
}

void ModuleRegistry::Start(ModuleList* modules, Thread* thread) {
  for (auto it = modules->list_.begin(); it != modules->list_.end(); it++) {
    Start(*it, thread);
  }
}

void ModuleRegistry::set_registry_and_handler(Module* instance, Thread* thread) const {
  instance->registry_ = this;
  instance->handler_ = new Handler(thread);
}

Module* ModuleRegistry::Start(const ModuleFactory* module, Thread* thread) {
  auto started_instance = started_modules_.find(module);
  if (started_instance != started_modules_.end()) {
    return started_instance->second;
  }

  LOG_DEBUG("Constructing next module");
  Module* instance = module->ctor_();
  last_instance_ = "starting " + instance->ToString();
  set_registry_and_handler(instance, thread);

  LOG_DEBUG("Starting dependencies of %s", instance->ToString().c_str());
  instance->ListDependencies(&instance->dependencies_);
  Start(&instance->dependencies_, thread);

  LOG_DEBUG("Finished starting dependencies and calling Start() of %s", instance->ToString().c_str());

  instance->Start();
  start_order_.push_back(module);
  started_modules_[module] = instance;
  LOG_DEBUG("Started %s", instance->ToString().c_str());
  return instance;
}

void ModuleRegistry::StopAll() {
  // Since modules were brought up in dependency order, it is safe to tear down by going in reverse order.
  for (auto it = start_order_.rbegin(); it != start_order_.rend(); it++) {
    auto instance = started_modules_.find(*it);
    ASSERT(instance != started_modules_.end());
    last_instance_ = "stopping " + instance->second->ToString();

    // Clear the handler before stopping the module to allow it to shut down gracefully.
    LOG_INFO("Stopping Handler of Module %s", instance->second->ToString().c_str());
    instance->second->handler_->Clear();
    instance->second->handler_->WaitUntilStopped(kModuleStopTimeout);
    LOG_INFO("Stopping Module %s", instance->second->ToString().c_str());
    instance->second->Stop();
  }
  for (auto it = start_order_.rbegin(); it != start_order_.rend(); it++) {
    auto instance = started_modules_.find(*it);
    ASSERT(instance != started_modules_.end());
    delete instance->second->handler_;
    delete instance->second;
    started_modules_.erase(instance);
  }

  ASSERT(started_modules_.empty());
  start_order_.clear();
}

os::Handler* ModuleRegistry::GetModuleHandler(const ModuleFactory* module) const {
  auto started_instance = started_modules_.find(module);
  if (started_instance != started_modules_.end()) {
    return started_instance->second->GetHandler();
  }
  return nullptr;
}

void ModuleDumper::DumpState(std::string* output) const {
  ASSERT(output != nullptr);

  flatbuffers::FlatBufferBuilder builder(1024);
  auto title = builder.CreateString(title_);

  auto init_flags_offset = dumpsys::InitFlags::Dump(&builder);
  auto wakelock_offset = WakelockManager::Get().GetDumpsysData(&builder);

  std::queue<DumpsysDataFinisher> queue;
  for (auto it = module_registry_.start_order_.rbegin(); it != module_registry_.start_order_.rend(); it++) {
    auto instance = module_registry_.started_modules_.find(*it);
    ASSERT(instance != module_registry_.started_modules_.end());
    queue.push(instance->second->GetDumpsysData(&builder));
  }

  DumpsysDataBuilder data_builder(builder);
  data_builder.add_title(title);
  data_builder.add_init_flags(init_flags_offset);
  data_builder.add_wakelock_manager_data(wakelock_offset);

  while (!queue.empty()) {
    queue.front()(&data_builder);
    queue.pop();
  }

  builder.Finish(data_builder.Finish());
  *output = std::string(builder.GetBufferPointer(), builder.GetBufferPointer() + builder.GetSize());
}

}  // namespace bluetooth
