// 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/ledger/bin/app/page_manager_container.h"

#include <lib/fidl/cpp/interface_request.h>
#include <lib/fit/function.h>

#include <string>

#include "src/ledger/bin/app/page_manager.h"
#include "src/ledger/bin/app/page_usage_listener.h"
#include "src/ledger/bin/app/types.h"
#include "src/ledger/bin/storage/public/types.h"
#include "src/lib/fxl/logging.h"

namespace ledger {

PageManagerContainer::PageManagerContainer(
    std::string ledger_name, storage::PageId page_id,
    PageUsageListener* page_usage_listener)
    : page_id_(page_id),
      connection_notifier_(std::move(ledger_name), std::move(page_id),
                           page_usage_listener) {}

PageManagerContainer::~PageManagerContainer() = default;

void PageManagerContainer::set_on_empty(fit::closure on_empty_callback) {
  on_empty_callback_ = std::move(on_empty_callback);
  connection_notifier_.set_on_empty([this] { CheckEmpty(); });
  if (page_manager_) {
    page_manager_->set_on_empty(
        [this] { connection_notifier_.UnregisterExternalRequests(); });
  }
}

void PageManagerContainer::BindPage(
    fidl::InterfaceRequest<Page> page_request,
    fit::function<void(storage::Status)> callback) {
  connection_notifier_.RegisterExternalRequest();

  if (status_ != storage::Status::OK) {
    callback(status_);
    return;
  }
  auto page_impl =
      std::make_unique<PageImpl>(page_id_, std::move(page_request));
  if (page_manager_) {
    page_manager_->AddPageImpl(std::move(page_impl), std::move(callback));
    return;
  }
  page_impls_.emplace_back(std::move(page_impl), std::move(callback));
}

void PageManagerContainer::NewInternalRequest(
    fit::function<void(storage::Status, ExpiringToken, PageManager*)>
        callback) {
  if (status_ != storage::Status::OK) {
    callback(status_, fit::defer<fit::closure>([] {}), nullptr);
    return;
  }

  if (page_manager_) {
    callback(status_, connection_notifier_.NewInternalRequestToken(),
             page_manager_.get());
    return;
  }

  internal_request_callbacks_.push_back(std::move(callback));
}

void PageManagerContainer::SetPageManager(
    storage::Status status, std::unique_ptr<PageManager> page_manager) {
  auto token = connection_notifier_.NewInternalRequestToken();
  TRACE_DURATION("ledger", "page_manager_container_set_page_manager");

  FXL_DCHECK(!page_manager_is_set_);
  FXL_DCHECK((status != storage::Status::OK) == !page_manager);
  status_ = status;
  page_manager_ = std::move(page_manager);
  page_manager_is_set_ = true;

  for (auto& [page_impl, callback] : page_impls_) {
    if (page_manager_) {
      page_manager_->AddPageImpl(std::move(page_impl), std::move(callback));
    } else {
      callback(status_);
    }
  }
  page_impls_.clear();

  for (auto& callback : internal_request_callbacks_) {
    if (!page_manager_) {
      callback(status_, fit::defer<fit::closure>([] {}), nullptr);
      continue;
    }
    callback(status_, connection_notifier_.NewInternalRequestToken(),
             page_manager_.get());
  }
  internal_request_callbacks_.clear();

  if (page_manager_) {
    page_manager_->set_on_empty(
        [this] { connection_notifier_.UnregisterExternalRequests(); });
  } else {
    connection_notifier_.UnregisterExternalRequests();
  }
  // |CheckEmpty| called when |token| goes out of scope.
}

bool PageManagerContainer::PageConnectionIsOpen() {
  return (page_manager_ && !page_manager_->IsEmpty()) || !page_impls_.empty();
}

void PageManagerContainer::CheckEmpty() {
  // The PageManagerContainer is not considered empty until |SetPageManager| has
  // been called.
  if (on_empty_callback_ && connection_notifier_.IsEmpty() &&
      page_manager_is_set_ && (!page_manager_ || page_manager_->IsEmpty())) {
    on_empty_callback_();
  }
}

}  // namespace ledger
