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

#include <fidl/fidl.test.compatibility/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/stdcompat/optional.h>
#include <lib/sys/cpp/component_context.h>
#include <zircon/status.h>

#include <cstdlib>
#include <iostream>
#include <string>

constexpr const char kEchoInterfaceName[] = "fidl.test.compatibility.Echo";

using namespace fidl_test_compatibility;

class EventProxy : public fidl::AsyncEventHandler<Echo> {
 public:
  explicit EventProxy(::fidl::ServerBindingRef<Echo>& server_binding)
      : server_binding_(server_binding), result_(fitx::ok()) {}

  void EchoMinimalEvent(fidl::Event<Echo::EchoMinimalEvent>& event) override {
    result_ = fidl::SendEvent(server_binding_)->EchoMinimalEvent();
    sync_completion_signal(&completion);
  }

  void EchoEvent(fidl::Event<Echo::EchoEvent>& event) override {
    result_ = fidl::SendEvent(server_binding_)->EchoEvent(std::move(event.value()));
    sync_completion_signal(&completion);
  }
  void OnEchoNamedEvent(fidl::Event<Echo::OnEchoNamedEvent>& event) override {
    result_ = fidl::SendEvent(server_binding_)->OnEchoNamedEvent(std::move(event.value()));
    sync_completion_signal(&completion);
  }
  void OnEchoTablePayloadEvent(fidl::Event<Echo::OnEchoTablePayloadEvent>& event) override {
    result_ = fidl::SendEvent(server_binding_)->OnEchoTablePayloadEvent(std::move(event));
    sync_completion_signal(&completion);
  }
  void OnEchoUnionPayloadEvent(fidl::Event<Echo::OnEchoUnionPayloadEvent>& event) override {
    result_ = fidl::SendEvent(server_binding_)->OnEchoUnionPayloadEvent(std::move(event));
    sync_completion_signal(&completion);
  }

  fitx::result<fidl::Error> WaitForEvent() {
    sync_completion_wait(&completion, ZX_TIME_INFINITE);
    return result_;
  }

 private:
  fidl::ServerBindingRef<Echo>& server_binding_;
  fitx::result<fidl::Error> result_;
  sync_completion_t completion;
};

class EchoClientApp {
 public:
  EchoClientApp(::std::string server_url)
      : context_(sys::ComponentContext::CreateAndServeOutgoingDirectory()),
        loop_(&kAsyncLoopConfigNoAttachToCurrentThread),
        client_(fidl::SharedClient<Echo>(ConnectTo(server_url), loop_.dispatcher())) {
    loop_.StartThread();
  }
  EchoClientApp(::std::string server_url, EventProxy* event_handler)
      : context_(sys::ComponentContext::CreateAndServeOutgoingDirectory()),
        loop_(&kAsyncLoopConfigNoAttachToCurrentThread),
        client_(
            fidl::SharedClient<Echo>(ConnectTo(server_url), loop_.dispatcher(), event_handler)) {
    loop_.StartThread();
  }

  ~EchoClientApp() { loop_.Quit(); }

  void EchoMinimal(::std::string forward_to_server,
                   fidl::ClientCallback<Echo::EchoMinimal> callback) {
    client_->EchoMinimal(std::move(forward_to_server)).ThenExactlyOnce(std::move(callback));
  }

  void EchoMinimalWithError(::std::string forward_to_server, RespondWith result_variant,
                            fidl::ClientCallback<Echo::EchoMinimalWithError> callback) {
    client_
        ->EchoMinimalWithError(
            EchoEchoMinimalWithErrorRequest(std::move(forward_to_server), result_variant))
        .ThenExactlyOnce(std::move(callback));
  }

  zx_status_t EchoMinimalNoRetVal(::std::string forward_to_server) {
    auto result = client_->EchoMinimalNoRetVal(std::move(forward_to_server));
    if (result.is_error()) {
      return result.error_value().status();
    }
    return ZX_OK;
  }

  void EchoStruct(Struct value, ::std::string forward_to_server,
                  fidl::ClientCallback<Echo::EchoStruct> callback) {
    client_->EchoStruct(EchoEchoStructRequest(std::move(value), std::move(forward_to_server)))
        .ThenExactlyOnce(std::move(callback));
  }

  void EchoStructWithError(Struct value, DefaultEnum err, ::std::string forward_to_server,
                           RespondWith result_variant,
                           fidl::ClientCallback<Echo::EchoStructWithError> callback) {
    client_
        ->EchoStructWithError(EchoEchoStructWithErrorRequest(
            std::move(value), err, std::move(forward_to_server), result_variant))
        .ThenExactlyOnce(std::move(callback));
  }

  zx_status_t EchoStructNoRetVal(Struct value, ::std::string forward_to_server) {
    auto result = client_->EchoStructNoRetVal(
        EchoEchoStructNoRetValRequest(std::move(value), std::move(forward_to_server)));
    if (result.is_error()) {
      return result.error_value().status();
    }
    return ZX_OK;
  }

  void EchoNamedStruct(fidl_test_imported::SimpleStruct value, ::std::string forward_to_server,
                       fidl::ClientCallback<Echo::EchoNamedStruct> callback) {
    client_
        ->EchoNamedStruct(
            fidl_test_imported::RequestStruct(std::move(value), std::move(forward_to_server)))
        .ThenExactlyOnce(std::move(callback));
  }

  void EchoNamedStructWithError(fidl_test_imported::SimpleStruct value, uint32_t err,
                                ::std::string forward_to_server,
                                fidl_test_imported::WantResponse result_variant,
                                fidl::ClientCallback<Echo::EchoNamedStructWithError> callback) {
    client_
        ->EchoNamedStructWithError(fidl_test_imported::ErrorableRequestStruct(
            std::move(value), err, std::move(forward_to_server), result_variant))
        .ThenExactlyOnce(std::move(callback));
  }

  zx_status_t EchoNamedStructNoRetVal(fidl_test_imported::SimpleStruct value,
                                      ::std::string forward_to_server) {
    auto result = client_->EchoNamedStructNoRetVal(fidl_test_imported::EventTriggeringRequestStruct(
        std::move(value), std::move(forward_to_server)));
    if (result.is_error()) {
      return result.error_value().status();
    }
    return ZX_OK;
  }

  void EchoArrays(ArraysStruct value, ::std::string forward_to_server,
                  fidl::ClientCallback<Echo::EchoArrays> callback) {
    client_->EchoArrays(EchoEchoArraysRequest(std::move(value), forward_to_server))
        .ThenExactlyOnce(std::move(callback));
  }

  void EchoArraysWithError(ArraysStruct value, DefaultEnum err, ::std::string forward_to_server,
                           RespondWith result_variant,
                           fidl::ClientCallback<Echo::EchoArraysWithError> callback) {
    client_
        ->EchoArraysWithError(EchoEchoArraysWithErrorRequest(
            std::move(value), err, std::move(forward_to_server), result_variant))
        .ThenExactlyOnce(std::move(callback));
  }

  void EchoVectors(VectorsStruct value, ::std::string forward_to_server,
                   fidl::ClientCallback<Echo::EchoVectors> callback) {
    client_->EchoVectors(EchoEchoVectorsRequest(std::move(value), std::move(forward_to_server)))
        .ThenExactlyOnce(std::move(callback));
  }

  void EchoVectorsWithError(VectorsStruct value, DefaultEnum err, ::std::string forward_to_server,
                            RespondWith result_variant,
                            fidl::ClientCallback<Echo::EchoVectorsWithError> callback) {
    client_
        ->EchoVectorsWithError(EchoEchoVectorsWithErrorRequest(
            std::move(value), err, std::move(forward_to_server), result_variant))
        .ThenExactlyOnce(std::move(callback));
  }

  void EchoTable(AllTypesTable value, ::std::string forward_to_server,
                 fidl::ClientCallback<Echo::EchoTable> callback) {
    return client_->EchoTable(EchoEchoTableRequest(std::move(value), forward_to_server))
        .ThenExactlyOnce(std::move(callback));
  }

  void EchoTableWithError(AllTypesTable value, DefaultEnum err, ::std::string forward_to_server,
                          RespondWith result_variant,
                          fidl::ClientCallback<Echo::EchoTableWithError> callback) {
    return client_
        ->EchoTableWithError(
            EchoEchoTableWithErrorRequest(std::move(value), err, forward_to_server, result_variant))
        .ThenExactlyOnce(std::move(callback));
  }

  void EchoXunions(::std::vector<AllTypesXunion> value, ::std::string forward_to_server,
                   fidl::ClientCallback<Echo::EchoXunions> callback) {
    client_->EchoXunions(EchoEchoXunionsRequest(std::move(value), std::move(forward_to_server)))
        .ThenExactlyOnce(std::move(callback));
  }

  void EchoXunionsWithError(::std::vector<AllTypesXunion> value, DefaultEnum err,
                            ::std::string forward_to_server, RespondWith result_variant,
                            fidl::ClientCallback<Echo::EchoXunionsWithError> callback) {
    client_
        ->EchoXunionsWithError(EchoEchoXunionsWithErrorRequest(
            std::move(value), err, std::move(forward_to_server), result_variant))
        .ThenExactlyOnce(std::move(callback));
  }

  void EchoTablePayload(fidl_test_compatibility::RequestTable payload,
                        fidl::ClientCallback<Echo::EchoTablePayload> callback) {
    client_->EchoTablePayload(std::move(payload)).ThenExactlyOnce(std::move(callback));
  }

  void EchoTablePayloadWithError(
      fidl_test_compatibility::EchoEchoTablePayloadWithErrorRequest payload,
      fidl::ClientCallback<Echo::EchoTablePayloadWithError> callback) {
    client_->EchoTablePayloadWithError(std::move(payload)).ThenExactlyOnce(std::move(callback));
  }

  zx_status_t EchoTablePayloadNoRetVal(fidl_test_compatibility::RequestTable payload) {
    auto result = client_->EchoTablePayloadNoRetVal(std::move(payload));
    if (result.is_error()) {
      return result.error_value().status();
    }
    return ZX_OK;
  }

  void EchoTableRequestComposed(
      ::fidl_test_imported::ComposedEchoTableRequestComposedRequest payload,
      fidl::ClientCallback<Echo::EchoTableRequestComposed> callback) {
    client_->EchoTableRequestComposed(std::move(payload)).ThenExactlyOnce(std::move(callback));
  }

  void EchoUnionPayload(fidl_test_compatibility::RequestUnion payload,
                        fidl::ClientCallback<Echo::EchoUnionPayload> callback) {
    return client_->EchoUnionPayload(std::move(payload)).ThenExactlyOnce(std::move(callback));
  }

  void EchoUnionPayloadWithError(
      fidl_test_compatibility::EchoEchoUnionPayloadWithErrorRequest payload,
      fidl::ClientCallback<Echo::EchoUnionPayloadWithError> callback) {
    return client_->EchoUnionPayloadWithError(std::move(payload))
        .ThenExactlyOnce(std::move(callback));
  }

  void EchoUnionResponseWithErrorComposed(
      int64_t value, bool want_absolute_value, ::std::string forward_to_server, uint32_t result_err,
      fidl_test_imported::WantResponse result_variant,
      fidl::ClientCallback<Echo::EchoUnionResponseWithErrorComposed> callback) {
    client_
        ->EchoUnionResponseWithErrorComposed(
            fidl_test_imported::ComposedEchoUnionResponseWithErrorComposedRequest(
                value, want_absolute_value, std::move(forward_to_server), result_err,
                std::move(result_variant)))
        .ThenExactlyOnce(std::move(callback));
  }

  zx_status_t EchoUnionPayloadNoRetVal(fidl_test_compatibility::RequestUnion payload) {
    auto result = client_->EchoUnionPayloadNoRetVal(std::move(payload));
    if (result.is_error()) {
      return result.error_value().status();
    }
    return ZX_OK;
  }

  EchoClientApp(const EchoClientApp&) = delete;
  EchoClientApp& operator=(const EchoClientApp&) = delete;

 private:
  // Called once upon construction to launch and connect to the server.
  ::fidl::ClientEnd<Echo> ConnectTo(::std::string server_url) {
    fuchsia::sys::LaunchInfo launch_info;
    launch_info.url = std::string(server_url.data(), server_url.size());
    echo_provider_ = sys::ServiceDirectory::CreateWithRequest(&launch_info.directory_request);

    fuchsia::sys::LauncherPtr launcher;
    context_->svc()->Connect(launcher.NewRequest());
    launcher->CreateComponent(std::move(launch_info), controller_.NewRequest());

    auto echo_ends = ::fidl::CreateEndpoints<Echo>();
    ZX_ASSERT(echo_ends.is_ok());
    ZX_ASSERT(echo_provider_->Connect(kEchoInterfaceName, echo_ends->server.TakeChannel()) ==
              ZX_OK);

    return std::move(echo_ends->client);
  }

  std::unique_ptr<sys::ComponentContext> context_;
  std::shared_ptr<sys::ServiceDirectory> echo_provider_;
  fuchsia::sys::ComponentControllerPtr controller_;
  async::Loop loop_;
  fidl::SharedClient<Echo> client_;
};

class EchoConnection final : public fidl::Server<Echo> {
 public:
  EchoConnection() = default;

  void EchoMinimal(EchoMinimalRequest& request, EchoMinimalCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      completer.Reply();
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoMinimal("", [completer = completer.ToAsync(), extend_lifetime = app](
                               fidl::Result<Echo::EchoMinimal>& result) mutable {
        ZX_ASSERT_MSG(result.is_ok(), "Forwarding failed: %s",
                      result.error_value().FormatDescription().c_str());
        completer.Reply();
      });
    }
  }

  void EchoMinimalWithError(EchoMinimalWithErrorRequest& request,
                            EchoMinimalWithErrorCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      if (request.result_variant() == wire::RespondWith::kErr) {
        completer.Reply(fitx::error(0u));
      } else {
        completer.Reply(fitx::ok());
      }
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoMinimalWithError(
          "", request.result_variant(),
          [completer = completer.ToAsync(),
           extend_lifetime = app](fidl::Result<Echo::EchoMinimalWithError>& result) mutable {
            ZX_ASSERT_MSG(result.is_ok() || result.error_value().is_application_error(),
                          "Forwarding failed: %s",
                          result.error_value().FormatDescription().c_str());
            if (result.is_ok()) {
              completer.Reply(fitx::ok());
            } else {
              completer.Reply(fitx::error(result.error_value().application_error()));
            }
          });
    }
  }

  void EchoMinimalNoRetVal(EchoMinimalNoRetValRequest& request,
                           EchoMinimalNoRetValCompleter::Sync&) override {
    if (request.forward_to_server().empty()) {
      auto result = fidl::SendEvent(server_binding_.value())->EchoMinimalEvent();
      ZX_ASSERT_MSG(result.is_ok(), "Replying with event failed: %s",
                    result.error_value().FormatDescription().c_str());
    } else {
      EventProxy event_handler(server_binding_.value());
      EchoClientApp app(request.forward_to_server(), &event_handler);
      zx_status_t status = app.EchoMinimalNoRetVal("");
      ZX_ASSERT_MSG(status == ZX_OK, "Replying with event failed direct: %s",
                    zx_status_get_string(status));
      auto result = event_handler.WaitForEvent();
      ZX_ASSERT_MSG(result.is_ok(), "Replying with event failed indirect: %s",
                    result.error_value().FormatDescription().c_str());
    }
  }

  void EchoStruct(EchoStructRequest& request, EchoStructCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      completer.Reply(std::move(request.value()));
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoStruct(std::move(request.value()), "",
                      [completer = completer.ToAsync(),
                       extend_lifetime = app](fidl::Result<Echo::EchoStruct>& result) mutable {
                        ZX_ASSERT_MSG(result.is_ok(), "Forwarding failed: %s",
                                      result.error_value().FormatDescription().c_str());
                        completer.Reply(std::move(result->value()));
                      });
    }
  }

  void EchoStructWithError(EchoStructWithErrorRequest& request,
                           EchoStructWithErrorCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      if (request.result_variant() == wire::RespondWith::kErr) {
        completer.Reply(fitx::error(request.result_err()));
      } else {
        completer.Reply(fitx::ok(std::move(request.value())));
      }
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoStructWithError(
          std::move(request.value()), request.result_err(), "", request.result_variant(),
          [completer = completer.ToAsync(),
           extend_lifetime = app](fidl::Result<Echo::EchoStructWithError>& result) mutable {
            ZX_ASSERT_MSG(result.is_ok() || result.error_value().is_application_error(),
                          "Forwarding failed: %s",
                          result.error_value().FormatDescription().c_str());
            if (result.is_ok()) {
              completer.Reply(fitx::ok(std::move(result.value())));
            } else {
              completer.Reply(fitx::error(result.error_value().application_error()));
            }
          });
    }
  }

  void EchoStructNoRetVal(EchoStructNoRetValRequest& request,
                          EchoStructNoRetValCompleter::Sync&) override {
    if (request.forward_to_server().empty()) {
      fitx::result<fidl::Error> result =
          fidl::SendEvent(server_binding_.value())->EchoEvent(std::move(request.value()));
      ZX_ASSERT_MSG(result.is_ok(), "Replying with event failed: %s",
                    result.error_value().FormatDescription().c_str());
    } else {
      EventProxy event_handler(server_binding_.value());
      EchoClientApp app(request.forward_to_server(), &event_handler);
      zx_status_t status = app.EchoStructNoRetVal(std::move(request.value()), "");
      ZX_ASSERT_MSG(status == ZX_OK, "Replying with event failed direct: %s",
                    zx_status_get_string(status));
      auto result = event_handler.WaitForEvent();
      ZX_ASSERT_MSG(result.is_ok(), "Replying with event failed indirect: %s",
                    result.error_value().FormatDescription().c_str());
    }
  }

  void EchoNamedStruct(EchoNamedStructRequest& request,
                       EchoNamedStructCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      completer.Reply(std::move(request.value()));
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoNamedStruct(std::move(request.value()), "",
                           [completer = completer.ToAsync(), extend_lifetime = app](
                               fidl::Result<Echo::EchoNamedStruct>& result) mutable {
                             ZX_ASSERT_MSG(result.is_ok(), "Forwarding failed: %s",
                                           result.error_value().FormatDescription().c_str());
                             completer.Reply(std::move(result->value()));
                           });
    }
  }

  void EchoNamedStructWithError(EchoNamedStructWithErrorRequest& request,
                                EchoNamedStructWithErrorCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      if (request.result_variant() == fidl_test_imported::WantResponse::kErr) {
        completer.Reply(fitx::error(request.result_err()));
      } else {
        completer.Reply(fitx::ok(std::move(request.value())));
      }
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoNamedStructWithError(
          std::move(request.value()), request.result_err(), "", request.result_variant(),
          [completer = completer.ToAsync(),
           extend_lifetime = app](fidl::Result<Echo::EchoNamedStructWithError>& result) mutable {
            ZX_ASSERT_MSG(result.is_ok() || result.error_value().is_application_error(),
                          "Forwarding failed: %s",
                          result.error_value().FormatDescription().c_str());
            if (result.is_ok()) {
              completer.Reply(fitx::ok(std::move(result.value())));
            } else {
              completer.Reply(fitx::error(result.error_value().application_error()));
            }
          });
    }
  }

  void EchoNamedStructNoRetVal(EchoNamedStructNoRetValRequest& request,
                               EchoNamedStructNoRetValCompleter::Sync&) override {
    if (request.forward_to_server().empty()) {
      fitx::result<fidl::Error> result =
          fidl::SendEvent(server_binding_.value())->OnEchoNamedEvent(std::move(request.value()));
      ZX_ASSERT_MSG(result.is_ok(), "Replying with event failed: %s",
                    result.error_value().FormatDescription().c_str());
    } else {
      EventProxy event_handler(server_binding_.value());
      EchoClientApp app(request.forward_to_server(), &event_handler);
      zx_status_t status = app.EchoNamedStructNoRetVal(std::move(request.value()), "");
      ZX_ASSERT_MSG(status == ZX_OK, "Replying with event failed direct: %s",
                    zx_status_get_string(status));
      auto result = event_handler.WaitForEvent();
      ZX_ASSERT_MSG(result.is_ok(), "Replying with event failed indirect: %s",
                    result.error_value().FormatDescription().c_str());
    }
  }

  void EchoArrays(EchoArraysRequest& request, EchoArraysCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      completer.Reply(std::move(request.value()));
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoArrays(std::move(request.value()), "",
                      [completer = completer.ToAsync(),
                       extend_lifetime = app](fidl::Result<Echo::EchoArrays>& result) mutable {
                        ZX_ASSERT_MSG(result.is_ok(), "Forwarding failed: %s",
                                      result.error_value().FormatDescription().c_str());
                        completer.Reply(std::move(result->value()));
                      });
    }
  }

  void EchoArraysWithError(EchoArraysWithErrorRequest& request,
                           EchoArraysWithErrorCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      if (request.result_variant() == wire::RespondWith::kErr) {
        completer.Reply(fitx::error(request.result_err()));
      } else {
        completer.Reply(fitx::ok(std::move(request.value())));
      }
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoArraysWithError(
          std::move(request.value()), request.result_err(), "", request.result_variant(),
          [completer = completer.ToAsync(),
           extend_lifetime = app](fidl::Result<Echo::EchoArraysWithError>& result) mutable {
            ZX_ASSERT_MSG(result.is_ok() || result.error_value().is_application_error(),
                          "Forwarding failed: %s",
                          result.error_value().FormatDescription().c_str());
            if (result.is_ok()) {
              completer.Reply(fitx::ok(std::move(result.value())));
            } else {
              completer.Reply(fitx::error(result.error_value().application_error()));
            }
          });
    }
  }

  void EchoVectors(EchoVectorsRequest& request, EchoVectorsCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      completer.Reply(std::move(request.value()));
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoVectors(std::move(request.value()), "",
                       [completer = completer.ToAsync(),
                        extend_lifetime = app](fidl::Result<Echo::EchoVectors>& result) mutable {
                         ZX_ASSERT_MSG(result.is_ok(), "Forwarding failed: %s",
                                       result.error_value().FormatDescription().c_str());
                         completer.Reply(std::move(result->value()));
                       });
    }
  }

  void EchoVectorsWithError(EchoVectorsWithErrorRequest& request,
                            EchoVectorsWithErrorCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      if (request.result_variant() == wire::RespondWith::kErr) {
        completer.Reply(fitx::error(request.result_err()));
      } else {
        completer.Reply(fitx::ok(std::move(request.value())));
      }
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoVectorsWithError(
          std::move(request.value()), request.result_err(), "", request.result_variant(),
          [completer = completer.ToAsync(),
           extend_lifetime = app](fidl::Result<Echo::EchoVectorsWithError>& result) mutable {
            ZX_ASSERT_MSG(result.is_ok() || result.error_value().is_application_error(),
                          "Forwarding failed: %s",
                          result.error_value().FormatDescription().c_str());
            if (result.is_ok()) {
              completer.Reply(fitx::ok(std::move(result.value())));
            } else {
              completer.Reply(fitx::error(result.error_value().application_error()));
            }
          });
    }
  }

  void EchoTable(EchoTableRequest& request, EchoTableCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      completer.Reply(std::move(request.value()));
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoTable(std::move(request.value()), "",
                     [completer = completer.ToAsync(),
                      extend_lifetime = app](fidl::Result<Echo::EchoTable>& result) mutable {
                       ZX_ASSERT_MSG(result.is_ok(), "Forwarding failed: %s",
                                     result.error_value().FormatDescription().c_str());
                       completer.Reply(std::move(result->value()));
                     });
    }
  }

  void EchoTableWithError(EchoTableWithErrorRequest& request,
                          EchoTableWithErrorCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      if (request.result_variant() == wire::RespondWith::kErr) {
        completer.Reply(fitx::error(request.result_err()));
      } else {
        completer.Reply(fitx::ok(std::move(request.value())));
      }
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoTableWithError(
          std::move(request.value()), request.result_err(), "", request.result_variant(),
          [completer = completer.ToAsync(),
           extend_lifetime = app](fidl::Result<Echo::EchoTableWithError>& result) mutable {
            ZX_ASSERT_MSG(result.is_ok() || result.error_value().is_application_error(),
                          "Forwarding failed: %s",
                          result.error_value().FormatDescription().c_str());
            if (result.is_ok()) {
              completer.Reply(fitx::ok(std::move(result.value())));
            } else {
              completer.Reply(fitx::error(result.error_value().application_error()));
            }
          });
    }
  }

  void EchoXunions(EchoXunionsRequest& request, EchoXunionsCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      completer.Reply(std::move(request.value()));
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoXunions(std::move(request.value()), "",
                       [completer = completer.ToAsync(),
                        extend_lifetime = app](fidl::Result<Echo::EchoXunions>& result) mutable {
                         ZX_ASSERT_MSG(result.is_ok(), "Forwarding failed: %s",
                                       result.error_value().FormatDescription().c_str());
                         completer.Reply(std::move(result->value()));
                       });
    }
  }

  void EchoXunionsWithError(EchoXunionsWithErrorRequest& request,
                            EchoXunionsWithErrorCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      if (request.result_variant() == wire::RespondWith::kErr) {
        completer.Reply(fitx::error(request.result_err()));
      } else {
        completer.Reply(fitx::ok(std::move(request.value())));
      }
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      app->EchoXunionsWithError(
          std::move(request.value()), request.result_err(), "", request.result_variant(),
          [completer = completer.ToAsync(),
           extend_lifetime = app](fidl::Result<Echo::EchoXunionsWithError>& result) mutable {
            ZX_ASSERT_MSG(result.is_ok() || result.error_value().is_application_error(),
                          "Forwarding failed: %s",
                          result.error_value().FormatDescription().c_str());
            if (result.is_ok()) {
              completer.Reply(fitx::ok(std::move(result.value())));
            } else {
              completer.Reply(fitx::error(result.error_value().application_error()));
            }
          });
    }
  }

  void EchoTablePayload(EchoTablePayloadRequest& request,
                        EchoTablePayloadCompleter::Sync& completer) override {
    if (!request.forward_to_server().has_value()) {
      ::fidl_test_compatibility::ResponseTable resp{{.value = request.value()}};
      completer.Reply(std::move(resp));
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server().value());
      fidl_test_compatibility::RequestTable req{{.value = request.value()}};
      app->EchoTablePayload(std::move(req),
                            [completer = completer.ToAsync(), extend_lifetime = app](
                                fidl::Result<Echo::EchoTablePayload>& result) mutable {
                              ZX_ASSERT_MSG(result.is_ok(), "Forwarding failed: %s",
                                            result.error_value().FormatDescription().c_str());
                              completer.Reply(std::move(result.value()));
                            });
    }
  }

  void EchoTablePayloadWithError(EchoTablePayloadWithErrorRequest& request,
                                 EchoTablePayloadWithErrorCompleter::Sync& completer) override {
    if (!request.forward_to_server().has_value()) {
      if (request.result_variant() == wire::RespondWith::kErr) {
        completer.Reply(fitx::error(request.result_err().value()));
      } else {
        ::fidl_test_compatibility::ResponseTable resp{{.value = request.value()}};
        completer.Reply(fitx::ok(std::move(resp)));
      }
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server().value());
      EchoEchoTablePayloadWithErrorRequest req{{
          .value = request.value(),
          .result_err = request.result_err(),
          .result_variant = request.result_variant(),
      }};

      app->EchoTablePayloadWithError(
          std::move(req), [completer = completer.ToAsync(), extend_lifetime = app](
                              fidl::Result<Echo::EchoTablePayloadWithError>& result) mutable {
            ZX_ASSERT_MSG(result.is_ok() || result.error_value().is_application_error(),
                          "Forwarding failed: %s",
                          result.error_value().FormatDescription().c_str());
            if (result.is_ok()) {
              completer.Reply(fitx::ok(std::move(result.value())));
            } else {
              completer.Reply(fitx::error(result.error_value().application_error()));
            }
          });
    }
  }

  void EchoTablePayloadNoRetVal(EchoTablePayloadNoRetValRequest& request,
                                EchoTablePayloadNoRetValCompleter::Sync&) override {
    if (!request.forward_to_server().has_value()) {
      ::fidl_test_compatibility::ResponseTable resp{{.value = request.value()}};
      fitx::result<fidl::Error> result =
          fidl::SendEvent(server_binding_.value())->OnEchoTablePayloadEvent(std::move(resp));
      ZX_ASSERT_MSG(result.is_ok(), "Replying with event failed: %s",
                    result.error_value().FormatDescription().c_str());
    } else {
      EventProxy event_handler(server_binding_.value());
      EchoClientApp app(request.forward_to_server().value(), &event_handler);
      ::fidl_test_compatibility::RequestTable req{{.value = request.value()}};
      zx_status_t status = app.EchoTablePayloadNoRetVal(std::move(req));
      ZX_ASSERT_MSG(status == ZX_OK, "Replying with event failed direct: %s",
                    zx_status_get_string(status));
      auto result = event_handler.WaitForEvent();
      ZX_ASSERT_MSG(result.is_ok(), "Replying with event failed indirect: %s",
                    result.error_value().FormatDescription().c_str());
    }
  }

  void EchoTableRequestComposed(EchoTableRequestComposedRequest& request,
                                EchoTableRequestComposedCompleter::Sync& completer) override {
    if (!request.forward_to_server().has_value()) {
      fidl_test_imported::SimpleStruct resp(true, request.value().value());
      completer.Reply(std::move(resp));
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server().value());
      fidl_test_imported::ComposedEchoTableRequestComposedRequest req{{.value = request.value()}};
      app->EchoTableRequestComposed(
          std::move(req), [completer = completer.ToAsync(), extend_lifetime = app](
                              fidl::Result<Echo::EchoTableRequestComposed>& result) mutable {
            ZX_ASSERT_MSG(result.is_ok(), "Forwarding failed: %s",
                          result.error_value().FormatDescription().c_str());
            completer.Reply(std::move(result.value()));
          });
    }
  }

  void EchoUnionPayload(EchoUnionPayloadRequest& request,
                        EchoUnionPayloadCompleter::Sync& completer) override {
    const std::string& forward_to_server = request.signed_()
                                               ? request.signed_()->forward_to_server()
                                               : request.unsigned_()->forward_to_server();
    if (forward_to_server.empty()) {
      if (request.Which() == RequestUnion::Tag::kSigned) {
        completer.Reply(ResponseUnion::WithSigned_(request.signed_()->value()));
      } else {
        completer.Reply(ResponseUnion::WithUnsigned_(request.unsigned_()->value()));
      }
    } else {
      std::shared_ptr<EchoClientApp> app = std::make_shared<EchoClientApp>(forward_to_server);
      RequestUnion req;
      if (request.Which() == RequestUnion::Tag::kSigned) {
        req = RequestUnion::WithSigned_(
            ::fidl_test_compatibility::Signed(request.signed_()->value(), ""));
      } else {
        req = RequestUnion::WithUnsigned_(
            ::fidl_test_compatibility::Unsigned(request.unsigned_()->value(), ""));
      }
      app->EchoUnionPayload(std::move(req),
                            [completer = completer.ToAsync(), extend_lifetime = app](
                                fidl::Result<Echo::EchoUnionPayload>& result) mutable {
                              ZX_ASSERT_MSG(result.is_ok(), "Forwarding failed: %s",
                                            result.error_value().FormatDescription().c_str());
                              completer.Reply(std::move(result.value()));
                            });
    }
  }

  void EchoUnionPayloadWithError(EchoUnionPayloadWithErrorRequest& request,
                                 EchoUnionPayloadWithErrorCompleter::Sync& completer) override {
    const std::string& forward_to_server = request.signed_()
                                               ? request.signed_()->forward_to_server()
                                               : request.unsigned_()->forward_to_server();
    if (forward_to_server.empty()) {
      RespondWith result_variant = request.signed_() ? request.signed_()->result_variant()
                                                     : request.unsigned_()->result_variant();
      if (result_variant == wire::RespondWith::kErr) {
        DefaultEnum err =
            request.signed_() ? request.signed_()->result_err() : request.unsigned_()->result_err();
        completer.Reply(fitx::error(err));
      } else {
        if (request.Which() == EchoEchoUnionPayloadWithErrorRequest::Tag::kSigned) {
          completer.Reply(fitx::ok(ResponseUnion::WithSigned_(request.signed_()->value())));
        } else {
          completer.Reply(fitx::ok(ResponseUnion::WithUnsigned_(request.unsigned_()->value())));
        }
      }
    } else {
      std::shared_ptr<EchoClientApp> app = std::make_shared<EchoClientApp>(forward_to_server);
      EchoEchoUnionPayloadWithErrorRequest req;
      if (request.Which() == EchoEchoUnionPayloadWithErrorRequest::Tag::kSigned) {
        auto variant = request.signed_();
        req = EchoEchoUnionPayloadWithErrorRequest::WithSigned_(
            ::fidl_test_compatibility::SignedErrorable(variant->value(), "", variant->result_err(),
                                                       variant->result_variant()));
      } else {
        auto variant = request.unsigned_();
        req = EchoEchoUnionPayloadWithErrorRequest::WithUnsigned_(
            ::fidl_test_compatibility::UnsignedErrorable(
                variant->value(), "", variant->result_err(), variant->result_variant()));
      }

      app->EchoUnionPayloadWithError(
          std::move(req), [completer = completer.ToAsync(), extend_lifetime = app](
                              fidl::Result<Echo::EchoUnionPayloadWithError>& result) mutable {
            ZX_ASSERT_MSG(result.is_ok() || result.error_value().is_application_error(),
                          "Forwarding failed: %s",
                          result.error_value().FormatDescription().c_str());
            if (result.is_ok()) {
              completer.Reply(fitx::ok(std::move(result.value())));
            } else {
              completer.Reply(fitx::error(result.error_value().application_error()));
            }
          });
    }
  }

  void EchoUnionPayloadNoRetVal(EchoUnionPayloadNoRetValRequest& request,
                                EchoUnionPayloadNoRetValCompleter::Sync&) override {
    const std::string& forward_to_server = request.signed_()
                                               ? request.signed_()->forward_to_server()
                                               : request.unsigned_()->forward_to_server();
    if (forward_to_server.empty()) {
      ResponseUnion resp = request.Which() == RequestUnion::Tag::kSigned
                               ? ResponseUnion::WithSigned_(request.signed_()->value())
                               : ResponseUnion::WithUnsigned_(request.unsigned_()->value());
      fitx::result<fidl::Error> result =
          fidl::SendEvent(server_binding_.value())->OnEchoUnionPayloadEvent(std::move(resp));
      ZX_ASSERT_MSG(result.is_ok(), "Replying with event failed: %s",
                    result.error_value().FormatDescription().c_str());
    } else {
      EventProxy event_handler(server_binding_.value());
      EchoClientApp app(forward_to_server, &event_handler);
      RequestUnion req;
      if (request.Which() == RequestUnion::Tag::kSigned) {
        req = RequestUnion::WithSigned_(
            ::fidl_test_compatibility::Signed(request.signed_()->value(), ""));
      } else {
        req = RequestUnion::WithUnsigned_(
            ::fidl_test_compatibility::Unsigned(request.unsigned_()->value(), ""));
      }

      zx_status_t status = app.EchoUnionPayloadNoRetVal(std::move(req));
      ZX_ASSERT_MSG(status == ZX_OK, "Replying with event failed direct: %s",
                    zx_status_get_string(status));
      auto result = event_handler.WaitForEvent();
      ZX_ASSERT_MSG(result.is_ok(), "Replying with event failed indirect: %s",
                    result.error_value().FormatDescription().c_str());
    }
  }

  void EchoUnionResponseWithErrorComposed(
      EchoUnionResponseWithErrorComposedRequest& request,
      EchoUnionResponseWithErrorComposedCompleter::Sync& completer) override {
    if (request.forward_to_server().empty()) {
      if (request.result_variant() == fidl_test_imported::WantResponse::kErr) {
        completer.Reply(fitx::error(request.result_err()));
        return;
      }

      if (request.want_absolute_value()) {
        completer.Reply(fitx::ok(
            ::fidl_test_imported::ComposedEchoUnionResponseWithErrorComposedResponse::WithUnsigned_(
                static_cast<uint64_t>(std::abs(request.value())))));
      } else {
        completer.Reply(fitx::ok(
            ::fidl_test_imported::ComposedEchoUnionResponseWithErrorComposedResponse::WithSigned_(
                request.value())));
      }
    } else {
      std::shared_ptr<EchoClientApp> app =
          std::make_shared<EchoClientApp>(request.forward_to_server());
      request.forward_to_server() = "";
      fidl_test_imported::ComposedEchoTableRequestComposedRequest req{{.value = request.value()}};
      app->EchoUnionResponseWithErrorComposed(
          request.value(), request.want_absolute_value(), "", request.result_err(),
          request.result_variant(),
          [completer = completer.ToAsync(), extend_lifetime = app](
              fidl::Result<Echo::EchoUnionResponseWithErrorComposed>& result) mutable {
            ZX_ASSERT_MSG(result.is_ok() || result.error_value().is_application_error(),
                          "Forwarding failed: %s",
                          result.error_value().FormatDescription().c_str());
            if (result.is_ok()) {
              completer.Reply(fitx::ok(std::move(result.value())));
            } else {
              completer.Reply(fitx::error(result.error_value().application_error()));
            }
          });
    }
  }

  void set_server_binding(::fidl::ServerBindingRef<Echo> binding) {
    server_binding_.emplace(binding);
  }

 private:
  cpp17::optional<::fidl::ServerBindingRef<Echo>> server_binding_;
};

int main(int argc, const char** argv) {
  // The FIDL support lib requires a default async dispatcher.
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  auto context = sys::ComponentContext::CreateAndServeOutgoingDirectory();

  context->outgoing()->AddPublicService(
      std::make_unique<vfs::Service>([&](zx::channel request, async_dispatcher_t* dispatcher) {
        auto conn = std::make_unique<EchoConnection>();
        EchoConnection* conn_raw = conn.get();
        auto binding = ::fidl::BindServer(dispatcher, ::fidl::ServerEnd<Echo>(std::move(request)),
                                          std::move(conn));
        conn_raw->set_server_binding(std::move(binding));
      }),
      kEchoInterfaceName);

  loop.Run();
  return EXIT_SUCCESS;
}
