/*
 * 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.
 */

#pragma once

#include <flatbuffers/flatbuffers.h>
#include <functional>
#include <future>
#include <map>
#include <string>
#include <vector>

#include "common/bind.h"
#include "dumpsys_data_generated.h"
#include "os/handler.h"
#include "os/log.h"
#include "os/thread.h"

namespace bluetooth {

class Module;
class ModuleDumper;
class ModuleRegistry;
class TestModuleRegistry;
class FuzzTestModuleRegistry;

class ModuleFactory {
 friend ModuleRegistry;
 friend FuzzTestModuleRegistry;

public:
 ModuleFactory(std::function<Module*()> ctor);

private:
 std::function<Module*()> ctor_;
};

class ModuleList {
 friend Module;
 friend ModuleRegistry;

public:
 template <class T>
 void add() {
   list_.push_back(&T::Factory);
 }

 private:
  std::vector<const ModuleFactory*> list_;
};

using DumpsysDataFinisher = std::function<void(DumpsysDataBuilder* dumpsys_data_builder)>;

// Each leaf node module must have a factory like so:
//
// static const ModuleFactory Factory;
//
// which will provide a constructor for the module registry to call.
// The module registry will also use the factory as the identifier
// for that module.
class Module {
  friend ModuleDumper;
  friend ModuleRegistry;
  friend TestModuleRegistry;

 public:
  virtual ~Module() = default;
 protected:
  // Populate the provided list with modules that must start before yours
  virtual void ListDependencies(ModuleList* list) const = 0;

  // You can grab your started dependencies during or after this call
  // using GetDependency(), or access the module registry via GetModuleRegistry()
  virtual void Start() = 0;

  // Release all resources, you're about to be deleted
  virtual void Stop() = 0;

  // Get relevant state data from the module
  virtual DumpsysDataFinisher GetDumpsysData(flatbuffers::FlatBufferBuilder* builder) const;

  virtual std::string ToString() const = 0;

  ::bluetooth::os::Handler* GetHandler() const;

  const ModuleRegistry* GetModuleRegistry() const;

  template <class T>
  T* GetDependency() const {
    return static_cast<T*>(GetDependency(&T::Factory));
  }

  template <typename Functor, typename... Args>
  void Call(Functor&& functor, Args&&... args) {
    GetHandler()->Call(std::forward<Functor>(functor), std::forward<Args>(args)...);
  }

  template <typename T, typename Functor, typename... Args>
  void CallOn(T* obj, Functor&& functor, Args&&... args) {
    GetHandler()->CallOn(obj, std::forward<Functor>(functor), std::forward<Args>(args)...);
  }

 private:
  Module* GetDependency(const ModuleFactory* module) const;

  ::bluetooth::os::Handler* handler_ = nullptr;
  ModuleList dependencies_;
  const ModuleRegistry* registry_;
};

class ModuleRegistry {
 friend Module;
 friend ModuleDumper;
 friend class StackManager;
 public:
  template <class T>
  bool IsStarted() const {
    return IsStarted(&T::Factory);
  }

  bool IsStarted(const ModuleFactory* factory) const;

  // Start all the modules on this list and their dependencies
  // in dependency order
  void Start(ModuleList* modules, ::bluetooth::os::Thread* thread);

  template <class T>
  T* Start(::bluetooth::os::Thread* thread) {
    return static_cast<T*>(Start(&T::Factory, thread));
  }

  Module* Start(const ModuleFactory* id, ::bluetooth::os::Thread* thread);

  // Stop all running modules in reverse order of start
  void StopAll();

 protected:
  Module* Get(const ModuleFactory* module) const;

  void set_registry_and_handler(Module* instance, ::bluetooth::os::Thread* thread) const;

  os::Handler* GetModuleHandler(const ModuleFactory* module) const;

  std::map<const ModuleFactory*, Module*> started_modules_;
  std::vector<const ModuleFactory*> start_order_;
  std::string last_instance_;
};

class ModuleDumper {
 public:
  ModuleDumper(const ModuleRegistry& module_registry, const char* title)
      : module_registry_(module_registry), title_(title) {}
  void DumpState(std::string* output) const;

 private:
  const ModuleRegistry& module_registry_;
  const std::string title_;
};

class TestModuleRegistry : public ModuleRegistry {
 public:
  void InjectTestModule(const ModuleFactory* module, Module* instance) {
    start_order_.push_back(module);
    started_modules_[module] = instance;
    set_registry_and_handler(instance, &test_thread);
    instance->Start();
  }

  Module* GetModuleUnderTest(const ModuleFactory* module) const {
    return Get(module);
  }

  template <class T>
  T* GetModuleUnderTest() const {
    return static_cast<T*>(GetModuleUnderTest(&T::Factory));
  }

  os::Handler* GetTestModuleHandler(const ModuleFactory* module) const {
    return GetModuleHandler(module);
  }

  os::Thread& GetTestThread() {
    return test_thread;
  }

  bool SynchronizeModuleHandler(const ModuleFactory* module, std::chrono::milliseconds timeout) const {
    return SynchronizeHandler(GetTestModuleHandler(module), timeout);
  }

  bool SynchronizeHandler(os::Handler* handler, std::chrono::milliseconds timeout) const {
    std::promise<void> promise;
    auto future = promise.get_future();
    handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)));
    return future.wait_for(timeout) == std::future_status::ready;
  }

 private:
  os::Thread test_thread{"test_thread", os::Thread::Priority::NORMAL};
};

class FuzzTestModuleRegistry : public TestModuleRegistry {
 public:
  template <class T>
  T* Inject(const ModuleFactory* overriding) {
    Module* instance = T::Factory.ctor_();
    InjectTestModule(overriding, instance);
    return static_cast<T*>(instance);
  }

  template <class T>
  T* Start() {
    return ModuleRegistry::Start<T>(&GetTestThread());
  }

  void WaitForIdleAndStopAll() {
    if (!GetTestThread().GetReactor()->WaitForIdle(std::chrono::milliseconds(100))) {
      LOG_ERROR("idle timed out");
    }
    StopAll();
  }
};

}  // namespace bluetooth
