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

namespace top {

#ifdef __Fuchsia__

class Top;
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;
using TopHandle = ::fidl::InterfaceHandle<Top>;
namespace internal {
constexpr uint64_t kTop_GetFoo_Ordinal = 0xb3385a000000000lu;
constexpr uint64_t kTop_GetFoo_GenOrdinal = 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_RequestEncoder {
 public:
  static ::fidl::Message GetFoo(::fidl::Encoder* _encoder) {
    _encoder->Alloc(16 - sizeof(fidl_message_header_t));
    return _encoder->GetMessage();
  }
};

class Top_RequestDecoder {
 public:
  Top_RequestDecoder() = default;
  virtual ~Top_RequestDecoder() = default;
  static const fidl_type_t* GetType(uint64_t ordinal, bool* out_needs_response);
  zx_status_t Decode_(::fidl::Message request) {
    bool needs_response;
    const fidl_type_t* request_type =
        GetType(request.ordinal(), &needs_response);
    if (request_type == nullptr) {
      return ZX_ERR_NOT_SUPPORTED;
    }
    const char* error_msg = nullptr;
    zx_status_t status = request.Decode(request_type, &error_msg);
    if (status != ZX_OK) {
      FIDL_REPORT_DECODING_ERROR(request, request_type, error_msg);
      return status;
    }
    ::fidl::Decoder request_decoder(std::move(request));
    switch (request.ordinal()) {
      case internal::kTop_GetFoo_Ordinal:
      case internal::kTop_GetFoo_GenOrdinal: {
        GetFoo();
        break;
      }
      default: {
        status = ZX_ERR_NOT_SUPPORTED;
        break;
      }
    }
    return status;
  }
  virtual void GetFoo() = 0;
};

class Top_ResponseEncoder {
 public:
  static ::fidl::Message GetFoo(::fidl::Encoder* _encoder, ::bottom::Foo* foo) {
    _encoder->Alloc(24 - sizeof(fidl_message_header_t));
    ::fidl::Encode(_encoder, foo, 16);
    return _encoder->GetMessage();
  }
};

class Top_ResponseDecoder {
 public:
  Top_ResponseDecoder() = default;
  virtual ~Top_ResponseDecoder() = default;
  static const fidl_type_t* GetType(uint64_t ordinal);
  zx_status_t Decode_(::fidl::Message response) {
    const fidl_type_t* response_type = GetType(response.ordinal());
    if (response_type == nullptr) {
      return ZX_ERR_NOT_SUPPORTED;
    }
    const char* error_msg = nullptr;
    zx_status_t status = response.Decode(response_type, &error_msg);
    if (status != ZX_OK) {
      FIDL_REPORT_DECODING_ERROR(response, response_type, error_msg);
      return status;
    }
    ::fidl::Decoder response_decoder(std::move(response));
    switch (response.ordinal()) {
      case internal::kTop_GetFoo_Ordinal:
      case internal::kTop_GetFoo_GenOrdinal: {
        auto arg0 = ::fidl::DecodeAs<::bottom::Foo>(&response_decoder, 16);
        GetFoo(std::move(arg0));
        break;
      }
      default: {
        break;
      }
    }
    return ZX_OK;
  }
  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::Message 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 ::top::Top Top_clazz;
  explicit Top_Stub(Top_clazz* impl);
  ~Top_Stub() override;

  zx_status_t Dispatch_(::fidl::Message 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 top
namespace fidl {}  // namespace fidl
