// 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 PERIDOT_BIN_LEDGER_FIDL_ERROR_NOTIFIER_ERROR_NOTIFIER_BINDING_H_
#define PERIDOT_BIN_LEDGER_FIDL_ERROR_NOTIFIER_ERROR_NOTIFIER_BINDING_H_

#include <map>
#include <utility>

#include <lib/fidl/cpp/binding.h>
#include <lib/fidl/cpp/enum.h>
#include <lib/fit/function.h>
#include <lib/fxl/logging.h>

#include "peridot/bin/ledger/fidl/include/types.h"
#include "peridot/bin/ledger/sync_helper/sync_helper.h"

namespace ledger {

// Class for binding of FIDL interface  implementing the ErrorNotifier interface
// and using the error notifier delegate interface |D|.
// For a FIDL interface Foo, |D| is an interface named FooErrorNotifierDelegate
// that needs to be implemented by the user and passed to ErrorNotifierBinding.
//
// This class internally handles the following features:
// - Implement the |Sync| method.
// - Provides a factory for passing a callback to the companion implementation
//   that will handle reporting the error and closing the connection.
// - Provides a |WrapOperation| method that needs to be called on all callback
//   before passing to the companion implementation so that |Sync| can keep
//   track of what operations are currently in progress.
//
// This class exposes the following features:
// - Access to the methods of the underlying bindings.
// - Implement the |set_on_empty| method to be usable with AutoCleanableSet.
template <typename D>
class ErrorNotifierBinding {
 public:
  ErrorNotifierBinding(D* delegate) : impl_(delegate, this), binding_(&impl_) {
    binding_.set_error_handler(
        [this](zx_status_t /* status */) { CheckEmpty(); });
    sync_helper_.set_on_empty([this] { CheckEmpty(); });
  }

  ErrorNotifierBinding(
      D* delegate, fidl::InterfaceRequest<typename D::FidlInterface> request,
      async_dispatcher_t* dispatcher = nullptr)
      : ErrorNotifierBinding(delegate) {
    binding_.Bind(std::move(request), dispatcher);
  }

  void set_on_empty(fit::closure on_empty) { on_empty_ = std::move(on_empty); }
  bool empty() { return !binding_.is_bound() && sync_helper_.empty(); }

  fidl::InterfaceRequest<typename D::FidlInterface> Unbind() {
    return binding_.Unbind();
  }
  fidl::InterfaceHandle<typename D::FidlInterface> NewBinding(
      async_dispatcher_t* dispatcher = nullptr) {
    return binding_.NewBinding(dispatcher);
  }

  void Close(zx_status_t status) { binding_.Close(status); }

  void Close(ledger::Status status) { Close(static_cast<zx_status_t>(status)); }

 private:
  friend typename D::Impl;

  void Sync(fit::function<void()> callback) {
    sync_helper_.RegisterSynchronizationCallback(std::move(callback));
  }

  // Wraps a callback in another one that preprends a Status arguments and
  // handles the status in case of error.
  template <typename... Args>
  auto WrapOperation(const char* function_name,
                     fit::function<void(Args...)> callback) {
    return sync_helper_.WrapOperation(
        [this, function_name, callback = std::move(callback)](
            ::fuchsia::ledger::Status status, Args&&... args) {
          if (status == ::fuchsia::ledger::Status::OK) {
            callback(std::forward<Args>(args)...);
            return;
          }
          FXL_LOG(INFO) << "FIDL call " << D::Impl::kInterfaceName
                        << "::" << function_name
                        << " failed with status: " << fidl::ToUnderlying(status)
                        << ". Sending the epitaph and closing the connection.";
          Close(status);
        });
  }

  // Returns a new callback taking a ledger::Status. This callback will be
  // responsible, in case of error, to send the status back as an event and
  // close the connection to the client.
  auto NewErrorCallback(const char* function_name) {
    return WrapOperation(function_name, fit::closure([] {}));
  }

  void CheckEmpty() {
    if (empty() && on_empty_) {
      on_empty_();
    }
  }

  typename D::Impl impl_;
  fidl::Binding<typename D::FidlInterface> binding_;
  fit::closure on_empty_;
  SyncHelper sync_helper_;
};

}  // namespace ledger

#endif  // PERIDOT_BIN_LEDGER_FIDL_ERROR_NOTIFIER_ERROR_NOTIFIER_BINDING_H_
