// WARNING: This file is machine generated by fidlgen.

#pragma once

#include <bottom/cpp/fidl.h>
#include <middle/cpp/fidl.h>

#include "lib/fidl/cpp/internal/header.h"

//
// Domain objects declarations (i.e. "natural types" in unified bindings).
//
namespace fidl {
namespace test {
namespace foreigntypeinresponseusedthroughcompose {

#ifdef __Fuchsia__
class Top;
using TopHandle = ::fidl::InterfaceHandle<Top>;
#endif  // __Fuchsia__
#ifdef __Fuchsia__

namespace _internal {
extern "C" const fidl_type_t
    fidl_test_foreigntypeinresponseusedthroughcompose_TopGetFooRequestTable;
}

class Top_RequestEncoder {
 public:
  static ::fidl::HLCPPOutgoingMessage GetFoo(::fidl::Encoder* _encoder) {
    fidl_trace(WillHLCPPEncode);
    _encoder->Alloc(16 - sizeof(fidl_message_header_t));

    fidl_trace(
        DidHLCPPEncode,
        &_internal::
            fidl_test_foreigntypeinresponseusedthroughcompose_TopGetFooRequestTable,
        _encoder->GetPtr<const char>(0), _encoder->CurrentLength(),
        _encoder->CurrentHandleCount());

    return _encoder->GetMessage();
  }
};

namespace _internal {
extern "C" const fidl_type_t
    fidl_test_foreigntypeinresponseusedthroughcompose_TopGetFooResponseTable;
}

class Top_ResponseEncoder {
 public:
  static ::fidl::HLCPPOutgoingMessage GetFoo(::fidl::Encoder* _encoder,
                                             ::bottom::Foo* foo) {
    fidl_trace(WillHLCPPEncode);
    _encoder->Alloc(24 - sizeof(fidl_message_header_t));
    ::fidl::Encode(_encoder, foo, 16);

    fidl_trace(
        DidHLCPPEncode,
        &_internal::
            fidl_test_foreigntypeinresponseusedthroughcompose_TopGetFooResponseTable,
        _encoder->GetPtr<const char>(0), _encoder->CurrentLength(),
        _encoder->CurrentHandleCount());
    return _encoder->GetMessage();
  }
};

#endif  // __Fuchsia__
}  // namespace foreigntypeinresponseusedthroughcompose
}  // namespace test
}  // namespace fidl
namespace fidl {}  // namespace fidl

//
// Proxies and stubs declarations
//
namespace fidl {
namespace test {
namespace foreigntypeinresponseusedthroughcompose {

#ifdef __Fuchsia__
using TopPtr = ::fidl::InterfacePtr<Top>;
class Top_Proxy;
class Top_Stub;
class Top_EventSender;
class Top_Sync;
using TopSyncPtr = ::fidl::SynchronousInterfacePtr<Top>;
class Top_SyncProxy;

namespace internal {
constexpr uint64_t kTop_GetFoo_Ordinal = 0x6ae8d19bc98f3d92lu;

}  // namespace internal
#endif  // __Fuchsia__
#ifdef __Fuchsia__
class Top {
 public:
  using Proxy_ = Top_Proxy;
  using Stub_ = Top_Stub;
  using EventSender_ = Top_EventSender;
  using Sync_ = Top_Sync;
  virtual ~Top();
  using GetFooCallback = fit::function<void(::bottom::Foo)>;

  virtual void GetFoo(GetFooCallback callback) = 0;
};

class Top_RequestDecoder {
 public:
  Top_RequestDecoder() = default;
  virtual ~Top_RequestDecoder() = default;
  static const fidl_type_t* GetType(uint64_t ordinal, bool* out_needs_response);
  virtual void GetFoo() = 0;
};

class Top_ResponseDecoder {
 public:
  Top_ResponseDecoder() = default;
  virtual ~Top_ResponseDecoder() = default;
  static const fidl_type_t* GetType(uint64_t ordinal);
  virtual void GetFoo(::bottom::Foo foo) = 0;
};

class Top_EventSender {
 public:
  virtual ~Top_EventSender();
};

class Top_Sync {
 public:
  using Proxy_ = Top_SyncProxy;
  virtual ~Top_Sync();
  virtual zx_status_t GetFoo(::bottom::Foo* out_foo) = 0;
};

class Top_Proxy final : public ::fidl::internal::Proxy, public Top {
 public:
  explicit Top_Proxy(::fidl::internal::ProxyController* controller);
  ~Top_Proxy() override;

  zx_status_t Dispatch_(::fidl::HLCPPIncomingMessage message) override;
  void GetFoo(GetFooCallback callback) override;

 private:
  Top_Proxy(const Top_Proxy&) = delete;
  Top_Proxy& operator=(const Top_Proxy&) = delete;

  ::fidl::internal::ProxyController* controller_;
};

class Top_Stub final : public ::fidl::internal::Stub, public Top_EventSender {
 public:
  typedef class ::fidl::test::foreigntypeinresponseusedthroughcompose::Top
      Top_clazz;
  explicit Top_Stub(Top_clazz* impl);
  ~Top_Stub() override;

  zx_status_t Dispatch_(::fidl::HLCPPIncomingMessage message,
                        ::fidl::internal::PendingResponse response) override;

 private:
  Top_clazz* impl_;
};

class Top_SyncProxy : public Top_Sync {
 public:
  explicit Top_SyncProxy(::zx::channel channel);
  ~Top_SyncProxy() override;
  zx_status_t GetFoo(::bottom::Foo* out_foo) override;

 private:
  ::fidl::internal::SynchronousProxy proxy_;
  friend class ::fidl::SynchronousInterfacePtr<Top>;
};

#endif  // __Fuchsia__
}  // namespace foreigntypeinresponseusedthroughcompose
}  // namespace test
}  // namespace fidl
