// Copyright 2022 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 SRC_DEVICES_MISC_DRIVERS_COMPAT_SIMPLE_BINDING_H_
#define SRC_DEVICES_MISC_DRIVERS_COMPAT_SIMPLE_BINDING_H_

#include <lib/async/wait.h>
#include <lib/fidl/cpp/wire/server.h>
#include <lib/fidl/cpp/wire/transaction.h>
#include <lib/fit/function.h>
#include <lib/zx/channel.h>
#include <zircon/fidl.h>

#include <utility>

namespace devfs {

class SimpleBinding;

// A basic implementation of |fidl::Transaction|. Designed to work with
// |fidl::BindSingleInFlightOnly|, which pauses message dispatching when an asynchronous transaction
// is in-flight. The channel is owned by |SimpleBinding|. |SimpleBinding| ownership ping-pongs
// between this transaction and the async dispatcher.
class ChannelTransaction final : public fidl::Transaction {
 public:
  ChannelTransaction(zx_txid_t txid, std::unique_ptr<SimpleBinding> binding)
      : Transaction(), txid_(txid), binding_(std::move(binding)) {}

  ~ChannelTransaction() final;

  ChannelTransaction(ChannelTransaction&& other) noexcept : Transaction(std::move(other)) {
    if (this != &other) {
      MoveImpl(std::move(other));
    }
  }

  ChannelTransaction& operator=(ChannelTransaction&& other) noexcept {
    Transaction::operator=(std::move(other));
    if (this != &other) {
      MoveImpl(std::move(other));
    }
    return *this;
  }

  zx_status_t Reply(fidl::OutgoingMessage* message, fidl::WriteOptions write_options) final;

  void Close(zx_status_t epitaph) final;

  std::unique_ptr<fidl::Transaction> TakeOwnership() final;

 private:
  friend SimpleBinding;

  void Dispatch(fidl::IncomingHeaderAndMessage& msg);

  std::unique_ptr<SimpleBinding> TakeBinding() { return std::move(binding_); }

  void MoveImpl(ChannelTransaction&& other) noexcept {
    txid_ = other.txid_;
    other.txid_ = 0;
    binding_ = std::move(other.binding_);
  }

  zx_txid_t txid_ = 0;
  std::unique_ptr<SimpleBinding> binding_ = {};
};

using AnyOnChannelClosedFn = fit::callback<void(fidl::internal::IncomingMessageDispatcher*)>;

class SimpleBinding : private async_wait_t {
 public:
  SimpleBinding(async_dispatcher_t* dispatcher, zx::channel channel,
                fidl::internal::IncomingMessageDispatcher* interface,
                AnyOnChannelClosedFn on_channel_closed_fn);

  ~SimpleBinding();

  static void MessageHandler(async_dispatcher_t* dispatcher, async_wait_t* wait, zx_status_t status,
                             const zx_packet_signal_t* signal);

 private:
  friend ChannelTransaction;
  friend zx_status_t BeginWait(std::unique_ptr<SimpleBinding>* unique_binding);

  zx::unowned_channel channel() const { return zx::unowned_channel(async_wait_t::object); }

  async_dispatcher_t* dispatcher_;
  fidl::internal::IncomingMessageDispatcher* interface_;
  AnyOnChannelClosedFn on_channel_closed_fn_;
};

zx_status_t BeginWait(std::unique_ptr<SimpleBinding>* unique_binding);

}  // namespace devfs

#endif  // SRC_DEVICES_MISC_DRIVERS_COMPAT_SIMPLE_BINDING_H_
