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

#pragma once

#include <functional>
#include <type_traits>

#include <fbl/macros.h>
#include <lib/async/dispatcher.h>
#include <lib/fidl-async/bind.h>
#include <lib/zx/channel.h>
#include <zircon/assert.h>
#include <zircon/fidl.h>

namespace fidl {

// A wrapper class which helps binding operations to a channel, and which
// helps creating C-compatible member-binding functions.
//
// This class ensures that the "void*" context value passed to |fidl_bind|
// is the same value used to dispatch to member functions.
template <typename T>
struct Binder {
    // Bind a member of a base class to a FIDL dispatch function, to allow
    // compatibility with the C bindings.
    //
    // For a FIDL function:
    //
    //   1: MyFunction(Args) -> (ReturnValue);
    //
    // The following C signature will be generated by the FIDL compiler, and is expected in a
    // server's dispatch table that wishes to implement this interface:
    //
    //   zx_status_t MyFunction(void* ctx, Args... args, fidl_txn_t* txn);
    //
    // This functionality can be implemented with this helper like so:
    //
    //   class MyClass {
    //   public:
    //       zx_status_t FunctionImplementation(Args... args, fidl_txn_t* txn) { ... }
    //   };
    //
    //   fidl_MyInterface_ops_t ops = {
    //       .MyFunction = Binder<MyClass>::BindMember<&MyClass::FunctionImplementation>
    //   };
    //
    // Which will instantiate a function with a signature matching the auto-generated "MyFunction"
    // C binding, that automatically invokes the FunctionImplementation member function, using a
    // "MyClass" instance as context.
    template <auto Fn, typename... Args>
    static zx_status_t BindMember(Args... args) {
        auto memfn = std::mem_fn(Fn);
        return BindInternal(memfn, args...);
    }

    // Bind a disambiguated, overloaded member of a base class to a FIDL dispatch function, to allow
    // compatibility with the C bindings.
    //
    // For a FIDL function:
    //
    //   1: MyFunction(Args) -> (ReturnValue);
    //
    // The following C signature will be generated by the FIDL compiler, and is expected in a
    // server's dispatch table that wishes to implement this interface:
    //
    //   zx_status_t MyFunction(void* ctx, Args... args, fidl_txn_t* txn);
    //
    // This functionality can be implemented with this helper like so:
    //
    //   class MyClass {
    //   public:
    //       zx_status_t FunctionOverloaded(Args... args, fidl_txn_t* txn) { ... }
    //       zx_status_t FunctionOverloaded(OtherArgs... other_args);
    //   };
    //
    //   fidl_MyInterface_ops_t ops = {
    //       .MyFunction = Binder<MyClass>::BindMember<zx_status_t(Args..., fidl_txn_t*),
    //                                                 &MyClass::FunctionOverloaded>
    //   };
    //
    // Which will instantiate a function with a signature matching the auto-generated "MyFunction"
    // C binding, that automatically invokes the FunctionOverloaded member function matching the
    // specified signature, using a "MyClass" instance as context.
    template <typename FnSig, FnSig T::*Fn, typename... Args>
    static zx_status_t BindMember(Args... args) {
        auto memfn = std::mem_fn<FnSig, T>(Fn);
        return BindInternal(memfn, args...);
    }

    // A utility function which simplifies binding methods of derived methods to FIDL
    // dispatch functions.
    //
    // A typical use case would look like the following:
    //
    // FIDL:
    //
    //   1: MyFunction(Args) -> (ReturnValue);
    //
    // C++:
    //
    //   class MyClass {
    //   public:
    //       zx_status_t FunctionImplementation(Args... args, fidl_txn_t* txn) {
    //           ...;
    //       }
    //
    //       zx_status_t Bind(async_dispatcher_t* dispatcher, zx::channel channel) {
    //           static constexpr Interface_ops_t kOps = {
    //               .MyFunction = Binder<MyClass>::BindMember<&MyClass::FunctionImplementation>,
    //           };
    //           return Binder<MyClass>::BindOps<Dispatch>(dispatcher, channel, this, &kOps);
    //       }
    //   }
    //
    //   ...
    //
    //   MyClass instance;
    //   instance.Bind(dispatcher, channel);
    template <auto Dispatch, typename Ops>
    static zx_status_t BindOps(async_dispatcher_t* dispatcher, zx::channel channel,
                               T* ctx, const Ops* ops) {
        static_assert(std::is_same<decltype(Dispatch),
                                   zx_status_t (*)(void*, fidl_txn_t*, fidl_msg_t*, const Ops* ops)>::value,
                      "Invalid dispatch function");
        return fidl_bind(dispatcher, channel.release(),
                         reinterpret_cast<fidl_dispatch_t*>(Dispatch), ctx, ops);
    }

private:
    template <typename MemFn, typename ...Args>
    static zx_status_t BindInternal(MemFn memfn, void* ctx, Args... args) {
        auto instance = static_cast<T*>(ctx);
        return memfn(instance, args...);
    }
};

// Wrapper class around |fidl_async_txn_t|. This allows a transaction to be
// initialized, moved, reset, and completed without unintentionally "double completing"
// or "forgetting to complete".
class AsyncTransaction {
public:
    DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(AsyncTransaction);

    AsyncTransaction() : txn_(nullptr) {}
    explicit AsyncTransaction(fidl_txn_t* txn) : txn_(fidl_async_txn_create(txn)) {}
    explicit AsyncTransaction(AsyncTransaction&& other) : txn_(other.release()) {}
    AsyncTransaction& operator=(AsyncTransaction&& other) {
        Reinitialize(other.release());
        return *this;
    }

    ~AsyncTransaction() {
        Reinitialize();
    }

    // Acquires a reference to the |fidl_txn_t| backing this txn object.
    // This reference will be invalidated if any non-const operations are called
    // on |AsyncTransaction|.
    //
    // Should not be called if the underlying transaction is invalid.
    fidl_txn_t* Transaction() const {
        ZX_DEBUG_ASSERT(HasTransaction());
        return fidl_async_txn_borrow(txn_);
    }

    // Completes the transaction and rebinds the underlying channel against the binding.
    //
    // Causes the transaction to become invalid.
    //
    // Should not be called if the underlying transaction is invalid.
    zx_status_t Rebind() {
        ZX_DEBUG_ASSERT(HasTransaction());
        return fidl_async_txn_complete(release(), true);
    }

    // Completes the current transaction, if one exists, and causes |AsyncTransaction| to
    // track a new |txn|.
    //
    // If |txn| is nullptr, this function causes the underlying transaction to become invalid.
    void Reset(fidl_txn_t* txn = nullptr) {
        fidl_async_txn_t* async_txn = txn ? fidl_async_txn_create(txn) : nullptr;
        Reinitialize(async_txn);
    }

private:
    bool HasTransaction() const {
        return txn_ != nullptr;
    }

    __attribute__((warn_unused_result)) fidl_async_txn_t* release() {
        fidl_async_txn_t* txn = txn_;
        txn_ = nullptr;
        return txn;
    }

    void Reinitialize(fidl_async_txn_t* txn = nullptr) {
        if (HasTransaction()) {
            fidl_async_txn_complete(release(), false);
        }
        txn_ = txn;
    }

    fidl_async_txn_t* txn_;
};

} // namespace fidl
