// Copyright 2019 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.

#include "src/sys/appmgr/component_event_provider_impl.h"

#include <lib/async/default.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>

#include "src/lib/fxl/memory/weak_ptr.h"

namespace component {

ComponentEventProviderImpl::ComponentEventProviderImpl(fxl::WeakPtr<Realm> realm,
                                                       async_dispatcher_t* dispatcher)
    : executor_(dispatcher), binding_(this), realm_(realm), weak_ptr_factory_(this) {}

ComponentEventProviderImpl::~ComponentEventProviderImpl() = default;

void ComponentEventProviderImpl::SetListener(
    fidl::InterfaceHandle<fuchsia::sys::internal::ComponentEventListener> listener) {
  if (listener_.is_bound()) {
    return;
  }
  listener_ = listener.Bind();
  listener_.set_error_handler([this](zx_status_t status) {
    listener_.Unbind();
    listener_.set_error_handler(nullptr);
  });
  const zx_status_t status =
      async::PostTask(executor_.dispatcher(), [self = weak_ptr_factory_.GetWeakPtr()] {
        if (!self) {
          FX_DLOGS(WARNING) << "called posted task after exit, skipping callback";
          return;
        }
        self->NotifyOfExistingComponents();
      });
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Could not synthesize events for existing components: "
                   << zx_status_get_string(status);
  }
}

zx_status_t ComponentEventProviderImpl::Connect(
    fidl::InterfaceRequest<fuchsia::sys::internal::ComponentEventProvider> request) {
  if (binding_.is_bound()) {
    return ZX_ERR_BAD_STATE;
  }
  binding_.Bind(std::move(request));
  return ZX_OK;
}

void ComponentEventProviderImpl::NotifyComponentStarted(
    fuchsia::sys::internal::SourceIdentity component) {
  if (listener_.is_bound()) {
    listener_->OnStart(std::move(component));
  }
}

void ComponentEventProviderImpl::NotifyComponentStopped(
    fuchsia::sys::internal::SourceIdentity component) {
  if (listener_.is_bound()) {
    listener_->OnStop(std::move(component));
  }
}

void ComponentEventProviderImpl::NotifyComponentDirReady(
    fuchsia::sys::internal::SourceIdentity component,
    fidl::InterfaceHandle<fuchsia::io::Directory> directory) {
  if (listener_.is_bound()) {
    listener_->OnDiagnosticsDirReady(std::move(component), std::move(directory));
  }
}

std::vector<std::string> ComponentEventProviderImpl::RelativeRealmPath(
    const fxl::WeakPtr<Realm>& leaf_realm) {
  std::vector<std::string> relative_realm_path;
  auto realm = leaf_realm;

  // We stop traversing the realm tree bottom up until we arrive to this realm_ or the root.
  while (realm && realm.get() != realm_.get()) {
    relative_realm_path.push_back(realm->label());
    realm = realm->parent();
  }

  // We arrived to root and we couldn't find |realm_| therefore this realm is not in the path.
  // Just a sanity check, this shouldn't occur given that this provider only calls this method with
  // realms under it.
  if (realm.get() != realm_.get()) {
    FX_LOGS(ERROR) << "Unreachable: ComponentEventProvider attempted to get a relative realm path "
                   << "from a realm not in its tree";
    return {};
  }

  std::reverse(relative_realm_path.begin(), relative_realm_path.end());
  return relative_realm_path;
}

void ComponentEventProviderImpl::NotifyOfExistingComponents() {
  std::queue<fxl::WeakPtr<Realm>> pending_realms;
  pending_realms.push(realm_);
  while (!pending_realms.empty()) {
    auto realm = pending_realms.front();
    pending_realms.pop();

    // Make sure we notify about all components in sub-realms of this realm which don't have an
    // event listener attached.
    for (auto& pair : realm->children()) {
      if (!pair.second->realm()->HasComponentEventListenerBound()) {
        pending_realms.push(pair.second->realm()->weak_ptr());
      }
    }
    auto relative_realm_path = RelativeRealmPath(realm);

    // Notify about all components in this realm.
    for (auto& pair : realm->applications()) {
      NotifyAboutExistingComponent(relative_realm_path, pair.second);
    }

    // Notify about all components in runners in this realm.
    for (auto& pair : realm->runners()) {
      const auto& runner = pair.second;
      for (auto& comp_pair : runner->components()) {
        const auto& component_bridge = comp_pair.second;
        // Given that an environment might have been created with use_parent_runners, we need to get
        // its actual realm which might not be the realm where the runner is.
        fxl::WeakPtr<Realm> realm = component_bridge->realm();
        if (realm) {
          NotifyAboutExistingComponent(RelativeRealmPath(realm), component_bridge);
        }
      }
    }
  }
}

void ComponentEventProviderImpl::NotifyAboutExistingComponent(
    std::vector<std::string> relative_realm_path,
    std::shared_ptr<ComponentControllerBase> application) {
  fuchsia::sys::internal::SourceIdentity identity;
  identity.set_component_url(application->url());
  identity.set_component_name(application->label());
  identity.set_instance_id(application->hub_instance_id());
  identity.set_realm_path(relative_realm_path);
  NotifyComponentStarted(fidl::Clone(identity));

  // If the component doesn't have an out/diagnostics directory or its out/ directory ready
  // doesn't exist, the and_then combinator won't be executed. Once the component exposes a
  // diagnostics directory (if ever), the listener will be notified through the regular flow.
  executor_.schedule_task(application->GetDiagnosticsDir().and_then(
      [self = weak_ptr_factory_.GetWeakPtr(),
       identity = std::move(identity)](fidl::InterfaceHandle<fuchsia::io::Directory>& dir) mutable {
        if (self) {
          self->NotifyComponentDirReady(std::move(identity), std::move(dir));
        }
      }));
}

}  // namespace component
