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

#include "peridot/bin/context_engine/debug.h"

#include <lib/fidl/cpp/clone.h>
#include <lib/fidl/cpp/optional.h>

#include "peridot/bin/context_engine/context_repository.h"

namespace modular {

ContextDebugImpl::ContextDebugImpl(const ContextRepository* const repository)
    : repository_(repository), weak_ptr_factory_(this) {}
ContextDebugImpl::~ContextDebugImpl() = default;

fxl::WeakPtr<ContextDebugImpl> ContextDebugImpl::GetWeakPtr() {
  return weak_ptr_factory_.GetWeakPtr();
}

void ContextDebugImpl::OnValueChanged(
    const std::set<Id>& parent_ids, const Id& id,
    const fuchsia::modular::ContextValue& value) {
  fuchsia::modular::ContextDebugValue update;
  update.parent_ids.resize(0);
  for (const auto& it : parent_ids) {
    update.parent_ids.push_back(it);
  }
  update.id = id;
  fuchsia::modular::ContextValue value_clone;
  fidl::Clone(value, &value_clone);
  update.value = fidl::MakeOptional(std::move(value_clone));
  DispatchOneValue(std::move(update));
}

void ContextDebugImpl::OnValueRemoved(const Id& id) {
  fuchsia::modular::ContextDebugValue update;
  update.id = id;
  update.parent_ids.resize(0);
  DispatchOneValue(std::move(update));
}

void ContextDebugImpl::OnSubscriptionAdded(
    const Id& id, const fuchsia::modular::ContextQuery& query,
    const fuchsia::modular::SubscriptionDebugInfo& debug_info) {
  fuchsia::modular::ContextDebugSubscription update;
  update.id = id;
  fuchsia::modular::ContextQuery query_clone;
  fidl::Clone(query, &query_clone);
  update.query = fidl::MakeOptional(std::move(query_clone));
  fuchsia::modular::SubscriptionDebugInfo debug_info_clone;
  fidl::Clone(debug_info, &debug_info_clone);
  update.debug_info = fidl::MakeOptional(std::move(debug_info_clone));
  DispatchOneSubscription(std::move(update));
}

void ContextDebugImpl::OnSubscriptionRemoved(const Id& id) {
  fuchsia::modular::ContextDebugSubscription update;
  update.id = id;
  DispatchOneSubscription(std::move(update));
}

util::IdleWaiter* ContextDebugImpl::GetIdleWaiter() { return &idle_waiter_; }

void ContextDebugImpl::Watch(
    fidl::InterfaceHandle<fuchsia::modular::ContextDebugListener> listener) {
  FXL_LOG(INFO) << "Watch(): entered";
  auto listener_ptr = listener.Bind();
  // Build a complete state snapshot and send it to |listener|.
  std::vector<fuchsia::modular::ContextDebugValue> all_values;
  for (const auto& entry : repository_->values_) {
    fuchsia::modular::ContextDebugValue update;
    update.id = entry.first;
    fuchsia::modular::ContextValue value_clone;
    fidl::Clone(entry.second.value, &value_clone);
    update.value = fidl::MakeOptional(std::move(value_clone));
    update.parent_ids.resize(0);
    for (const auto& it : repository_->graph_.GetParents(entry.first)) {
      update.parent_ids.push_back(it);
    }
    all_values.push_back(std::move(update));
  }
  listener_ptr->OnValuesChanged(std::move(all_values));
  // TODO(thatguy): Add subscriptions.

  listeners_.AddInterfacePtr(std::move(listener_ptr));
}

void ContextDebugImpl::WaitUntilIdle(WaitUntilIdleCallback callback) {
  idle_waiter_.WaitUntilIdle(std::move(callback));
}

void ContextDebugImpl::DispatchOneValue(
    fuchsia::modular::ContextDebugValue value) {
  fidl::VectorPtr<fuchsia::modular::ContextDebugValue> values;
  values.push_back(std::move(value));
  DispatchValues(std::move(values));
}

void ContextDebugImpl::DispatchValues(
    fidl::VectorPtr<fuchsia::modular::ContextDebugValue> values) {
  for (const auto& listener : listeners_.ptrs()) {
    fidl::VectorPtr<fuchsia::modular::ContextDebugValue> values_clone;
    fidl::Clone(values, &values_clone);
    (*listener)->OnValuesChanged(values_clone.take());
  }
}

void ContextDebugImpl::DispatchOneSubscription(
    fuchsia::modular::ContextDebugSubscription value) {
  fidl::VectorPtr<fuchsia::modular::ContextDebugSubscription> values;
  values.push_back(std::move(value));
  DispatchSubscriptions(std::move(values));
}

void ContextDebugImpl::DispatchSubscriptions(
    fidl::VectorPtr<fuchsia::modular::ContextDebugSubscription> subscriptions) {
  for (const auto& listener : listeners_.ptrs()) {
    fidl::VectorPtr<fuchsia::modular::ContextDebugSubscription>
        subscriptions_clone;
    fidl::Clone(subscriptions, &subscriptions_clone);
    (*listener)->OnSubscriptionsChanged(subscriptions_clone.take());
  }
}

}  // namespace modular
