// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef PERIDOT_BIN_MODULE_RESOLVER_LOCAL_MODULE_RESOLVER_H_
#define PERIDOT_BIN_MODULE_RESOLVER_LOCAL_MODULE_RESOLVER_H_

#include <functional>
#include <memory>
#include <set>
#include <vector>

#include <fuchsia/modular/cpp/fidl.h>
#include <lib/async/cpp/operation.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fxl/memory/weak_ptr.h>

#include "peridot/lib/module_manifest_source/module_manifest_source.h"

namespace modular {

class LocalModuleResolver : fuchsia::modular::ModuleResolver,
                            fuchsia::modular::QueryHandler {
 public:
  LocalModuleResolver();
  ~LocalModuleResolver() override;

  // Adds a source of Module manifests to index. It is not allowed to call
  // AddSource() after Connect(). |name| must be unique.
  void AddSource(std::string name, std::unique_ptr<ModuleManifestSource> repo);

  void Connect(
      fidl::InterfaceRequest<fuchsia::modular::ModuleResolver> request);

  void BindQueryHandler(
      fidl::InterfaceRequest<fuchsia::modular::QueryHandler> request);

  // |ModuleResolver|
  void FindModules(fuchsia::modular::FindModulesQuery query,
                   FindModulesCallback callback) override;
  // |ModuleResolver|
  void FindModulesByTypes(fuchsia::modular::FindModulesByTypesQuery query,
                          FindModulesByTypesCallback callback) override;
  // |ModuleResolver|
  void GetModuleManifest(fidl::StringPtr module_id,
                         GetModuleManifestCallback callback) override;

 private:
  class FindModulesCall;
  class FindModulesByTypesCall;

  using ModuleUri = std::string;
  using RepoSource = std::string;
  // We use the module URI to identify the module manifest.
  using ManifestId = std::tuple<RepoSource, ModuleUri>;
  using ParameterName = std::string;
  using ParameterType = std::string;
  using Action = std::string;

  std::set<ManifestId> FindHandlers(ModuleUri handler);

  // |fuchsia::modular::QueryHandler|
  void OnQuery(fuchsia::modular::UserInput query,
               OnQueryCallback done) override;

  void OnSourceIdle(const std::string& source_name);
  void OnNewManifestEntry(const std::string& source_name, std::string id_in,
                          fuchsia::modular::ModuleManifest new_entry);
  void OnRemoveManifestEntry(const std::string& source_name, std::string id_in);

  void PeriodicCheckIfSourcesAreReady();

  bool AllSourcesAreReady() const {
    return ready_sources_.size() == sources_.size();
  }

  // TODO(thatguy): At some point, factor the index functions out of
  // LocalModuleResolver so that they can be re-used by the general all-modules
  // Ask handler.
  std::map<std::string, std::unique_ptr<ModuleManifestSource>> sources_;
  // Set of sources that have told us they are idle, meaning they have
  // sent us all manifests they knew about at construction time.
  std::set<std::string> ready_sources_;
  // Map of module manifest ID -> module manifest.
  using ManifestMap = std::map<ManifestId, fuchsia::modular::ModuleManifest>;
  ManifestMap manifests_;

  // action -> key in |manifests_|
  std::map<Action, std::set<ManifestId>> action_to_manifests_;
  // (parameter type, parameter name) -> key in |manifests_|
  std::map<std::pair<ParameterType, ParameterName>, std::set<ManifestId>>
      parameter_type_and_name_to_manifests_;
  //  (parameter type) -> keys in |manifests_|.
  std::map<ParameterType, std::set<ManifestId>> parameter_type_to_manifests_;

  fidl::BindingSet<fuchsia::modular::ModuleResolver> bindings_;
  fidl::Binding<fuchsia::modular::QueryHandler> query_handler_binding_;
  // These are buffered until AllSourcesAreReady() == true.
  std::vector<fidl::InterfaceRequest<fuchsia::modular::ModuleResolver>>
      pending_bindings_;

  bool already_checking_if_sources_are_ready_;

  OperationCollection operations_;

  fxl::WeakPtrFactory<LocalModuleResolver> weak_factory_;

  FXL_DISALLOW_COPY_AND_ASSIGN(LocalModuleResolver);
};

}  // namespace modular

#endif  // PERIDOT_BIN_MODULE_RESOLVER_LOCAL_MODULE_RESOLVER_H_
