// Copyright 2018 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 GARNET_BIN_APPMGR_SERVICE_PROVIDER_DIR_IMPL_H_
#define GARNET_BIN_APPMGR_SERVICE_PROVIDER_DIR_IMPL_H_

#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

#include <fs/pseudo-dir.h>
#include <fs/service.h>
#include <fs/synchronous-vfs.h>
#include <fuchsia/sys/cpp/fidl.h>
#include "lib/fidl/cpp/binding_set.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/memory/weak_ptr.h"

namespace component {

// A directory-like object which dynamically creates Service vnodes
// for any file lookup. It also exposes service provider interface.
//
// It supports enumeration for only first level of services.
class ServiceProviderDirImpl : public fuchsia::sys::ServiceProvider,
                               public fs::Vnode {
 public:
  explicit ServiceProviderDirImpl(
      const std::vector<std::string>* services = nullptr);
  ~ServiceProviderDirImpl() override;

  // Sets the parent of this. Parent should be fully initialized.
  void set_parent(fbl::RefPtr<ServiceProviderDirImpl> parent);

  void set_component_url(const std::string& url) {
    component_url_ = url;
  }

  void AddService(const std::string& service_name,
                  fbl::RefPtr<fs::Service> service);

  void AddBinding(
      fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> request);

  //
  // Overridden from |fs::Vnode|:
  //

  zx_status_t Lookup(fbl::RefPtr<fs::Vnode>* out, fbl::StringPiece name) final;

  zx_status_t Getattr(vnattr_t* a) final;

  zx_status_t Readdir(fs::vdircookie_t* cookie, void* dirents, size_t len,
                      size_t* out_actual) final;

  //
  // Overridden from |fuchsia::sys::ServiceProvider|:
  //

  void ConnectToService(std::string service_name,
                        zx::channel channel) override;

 private:
  bool IsServiceWhitelisted(const std::string& service_name) {
    return (!has_services_whitelist_ ||
            services_whitelist_.count(service_name) > 0);
  }

  fidl::BindingSet<fuchsia::sys::ServiceProvider> bindings_;
  fs::SynchronousVfs vfs_;
  // |root_| has all services offered by this provider (including those
  // inherited from the parent, if any).
  fbl::RefPtr<fs::PseudoDir> root_;
  fbl::RefPtr<ServiceProviderDirImpl> parent_;
  fxl::WeakPtrFactory<ServiceProviderDirImpl> weak_factory_;

  // TODO(CP-25): Remove has_services_whitelist_ when empty services is
  // equivalent to no services.
  bool has_services_whitelist_ = false;
  std::unordered_set<std::string> services_whitelist_;
  // Secondary storage for services under |root_| in a format that can easily
  // be consumed by children. Stored as vector to preserve order.
  typedef std::pair<std::string, fbl::RefPtr<fs::Service>> ServiceHandle;
  std::vector<ServiceHandle> service_handles_;
  std::unordered_set<std::string> all_service_names_;

  std::string component_url_ = "NO_COMPONENT";

  FXL_DISALLOW_COPY_AND_ASSIGN(ServiceProviderDirImpl);
};

}  // namespace component

#endif  // GARNET_BIN_APPMGR_SERVICE_PROVIDER_DIR_IMPL_H_
