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

#include <fidl/test/compatibility/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/channel.h>
#include <zircon/types.h>

#include <cstdlib>
#include <string>

#include "fidl/test/imported/cpp/fidl.h"
#include "src/tests/fidl/compatibility/hlcpp_client_app.h"

namespace fidl {
namespace test {
namespace compatibility {

class EchoServerApp : public Echo {
 public:
  explicit EchoServerApp(async::Loop* loop)
      : loop_(loop), context_(sys::ComponentContext::CreateAndServeOutgoingDirectory()) {
    context_->outgoing()->AddPublicService(bindings_.GetHandler(this));
  }

  ~EchoServerApp() {}

  void EchoMinimal(std::string forward_to_server, EchoMinimalCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoMinimal("", [this, &called_back, &callback]() {
        called_back = true;
        callback();
        loop_->Quit();
      });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      callback();
    }
  }

  void EchoMinimalWithError(std::string forward_to_server, RespondWith result_variant,
                            EchoMinimalWithErrorCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoMinimalWithError(
          "", result_variant,
          [this, &called_back, &callback](Echo_EchoMinimalWithError_Result result) {
            called_back = true;
            callback(std::move(result));
            loop_->Quit();
          });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      Echo_EchoMinimalWithError_Result result;
      if (result_variant == RespondWith::ERR) {
        result.set_err(0u);
      } else {
        result.set_response(Echo_EchoMinimalWithError_Response());
      }
      callback(std::move(result));
    }
  }

  void EchoMinimalNoRetVal(std::string forward_to_server) override {
    if (!forward_to_server.empty()) {
      std::unique_ptr<EchoClientApp> app(new EchoClientApp);
      app->echo().set_error_handler([this, forward_to_server](zx_status_t status) {
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app->Start(forward_to_server);
      app->echo().events().EchoMinimalEvent = [this]() { this->HandleEchoMinimalEvent(); };
      app->echo()->EchoMinimalNoRetVal("");
      client_apps_.push_back(std::move(app));
    } else {
      for (const auto& binding : bindings_.bindings()) {
        binding->events().EchoMinimalEvent();
      }
    }
  }

  void EchoStruct(Struct value, std::string forward_to_server,
                  EchoStructCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoStruct(std::move(value), "", [this, &called_back, &callback](Struct resp) {
        called_back = true;
        callback(std::move(resp));
        loop_->Quit();
      });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      callback(std::move(value));
    }
  }

  void EchoStructWithError(Struct value, default_enum err, std::string forward_to_server,
                           RespondWith result_variant,
                           EchoStructWithErrorCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoStructWithError(
          std::move(value), std::move(err), "", result_variant,
          [this, &called_back, &callback](Echo_EchoStructWithError_Result result) {
            called_back = true;
            callback(std::move(result));
            loop_->Quit();
          });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      Echo_EchoStructWithError_Result result;
      if (result_variant == RespondWith::ERR) {
        result.set_err(err);
      } else {
        result.set_response(Echo_EchoStructWithError_Response(std::move(value)));
      }
      callback(std::move(result));
    }
  }

  void EchoStructNoRetVal(Struct value, std::string forward_to_server) override {
    if (!forward_to_server.empty()) {
      std::unique_ptr<EchoClientApp> app(new EchoClientApp);
      app->echo().set_error_handler([this, forward_to_server](zx_status_t status) {
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app->Start(forward_to_server);
      app->echo().events().EchoEvent = [this](Struct resp) {
        this->HandleEchoEvent(std::move(resp));
      };
      app->echo()->EchoStructNoRetVal(std::move(value), "");
      client_apps_.push_back(std::move(app));
    } else {
      for (const auto& binding : bindings_.bindings()) {
        Struct to_send;
        value.Clone(&to_send);
        binding->events().EchoEvent(std::move(to_send));
      }
    }
  }

  void EchoArrays(ArraysStruct value, std::string forward_to_server,
                  EchoArraysCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoArrays(std::move(value), "",
                             [this, &called_back, &callback](ArraysStruct resp) {
                               called_back = true;
                               callback(std::move(resp));
                               loop_->Quit();
                             });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      callback(std::move(value));
    }
  }

  void EchoArraysWithError(ArraysStruct value, default_enum err, std::string forward_to_server,
                           RespondWith result_variant,
                           EchoArraysWithErrorCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoArraysWithError(
          std::move(value), std::move(err), "", result_variant,
          [this, &called_back, &callback](Echo_EchoArraysWithError_Result result) {
            called_back = true;
            callback(std::move(result));
            loop_->Quit();
          });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      Echo_EchoArraysWithError_Result result;
      if (result_variant == RespondWith::ERR) {
        result.set_err(err);
      } else {
        result.set_response(Echo_EchoArraysWithError_Response(std::move(value)));
      }
      callback(std::move(result));
    }
  }

  void EchoVectors(VectorsStruct value, std::string forward_to_server,
                   EchoVectorsCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoVectors(std::move(value), "",
                              [this, &called_back, &callback](VectorsStruct resp) {
                                called_back = true;
                                callback(std::move(resp));
                                loop_->Quit();
                              });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      callback(std::move(value));
    }
  }

  void EchoVectorsWithError(VectorsStruct value, default_enum err, std::string forward_to_server,
                            RespondWith result_variant,
                            EchoVectorsWithErrorCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoVectorsWithError(
          std::move(value), std::move(err), "", result_variant,
          [this, &called_back, &callback](Echo_EchoVectorsWithError_Result result) {
            called_back = true;
            callback(std::move(result));
            loop_->Quit();
          });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      Echo_EchoVectorsWithError_Result result;
      if (result_variant == RespondWith::ERR) {
        result.set_err(err);
      } else {
        result.set_response(Echo_EchoVectorsWithError_Response(std::move(value)));
      }
      callback(std::move(result));
    }
  }

  void EchoTable(AllTypesTable value, std::string forward_to_server,
                 EchoTableCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoTable(std::move(value), "",
                            [this, &called_back, &callback](AllTypesTable resp) {
                              called_back = true;
                              callback(std::move(resp));
                              loop_->Quit();
                            });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      callback(std::move(value));
    }
  }

  void EchoTableWithError(AllTypesTable value, default_enum err, std::string forward_to_server,
                          RespondWith result_variant,
                          EchoTableWithErrorCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoTableWithError(
          std::move(value), std::move(err), "", result_variant,
          [this, &called_back, &callback](Echo_EchoTableWithError_Result result) {
            called_back = true;
            callback(std::move(result));
            loop_->Quit();
          });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      Echo_EchoTableWithError_Result result;
      if (result_variant == RespondWith::ERR) {
        result.set_err(err);
      } else {
        result.set_response(Echo_EchoTableWithError_Response(std::move(value)));
      }
      callback(std::move(result));
    }
  }

  void EchoXunions(std::vector<AllTypesXunion> value, std::string forward_to_server,
                   EchoXunionsCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoXunions(std::move(value), "",
                              [this, &called_back, &callback](std::vector<AllTypesXunion> resp) {
                                called_back = true;
                                callback(std::move(resp));
                                loop_->Quit();
                              });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      callback(std::move(value));
    }
  }

  void EchoXunionsWithError(std::vector<AllTypesXunion> value, default_enum err,
                            std::string forward_to_server, RespondWith result_variant,
                            EchoXunionsWithErrorCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoXunionsWithError(
          std::move(value), std::move(err), "", result_variant,
          [this, &called_back, &callback](Echo_EchoXunionsWithError_Result result) {
            called_back = true;
            callback(std::move(result));
            loop_->Quit();
          });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      Echo_EchoXunionsWithError_Result result;
      if (result_variant == RespondWith::ERR) {
        result.set_err(err);
      } else {
        result.set_response(Echo_EchoXunionsWithError_Response(std::move(value)));
      }
      callback(std::move(result));
    }
  }

  void EchoNamedStruct(imported::SimpleStruct value, std::string forward_to_server,
                       EchoNamedStructCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoNamedStruct(std::move(value), "",
                                  [this, &called_back, &callback](imported::SimpleStruct resp) {
                                    called_back = true;
                                    callback(std::move(resp));
                                    loop_->Quit();
                                  });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      callback(std::move(value));
    }
  }

  void EchoNamedStructWithError(imported::SimpleStruct value, uint32_t err,
                                std::string forward_to_server,
                                imported::WantResponse result_variant,
                                EchoNamedStructWithErrorCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoNamedStructWithError(
          std::move(value), std::move(err), "", result_variant,
          [this, &called_back, &callback](Echo_EchoNamedStructWithError_Result result) {
            called_back = true;
            callback(std::move(result));
            loop_->Quit();
          });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      Echo_EchoNamedStructWithError_Result result;
      if (result_variant == imported::WantResponse::ERR) {
        result.set_err(err);
      } else {
        result.set_response(imported::ResponseStruct{std::move(value)});
      }
      callback(std::move(result));
    }
  }

  void EchoNamedStructNoRetVal(imported::SimpleStruct value,
                               std::string forward_to_server) override {
    if (!forward_to_server.empty()) {
      std::unique_ptr<EchoClientApp> app(new EchoClientApp);
      app->echo().set_error_handler([this, forward_to_server](zx_status_t status) {
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app->Start(forward_to_server);
      app->echo().events().OnEchoNamedEvent = [this](imported::SimpleStruct resp) {
        this->HandleOnEchoNamedEvent(std::move(resp));
      };
      app->echo()->EchoNamedStructNoRetVal(std::move(value), "");
      client_apps_.push_back(std::move(app));
    } else {
      for (const auto& binding : bindings_.bindings()) {
        imported::SimpleStruct to_send;
        value.Clone(&to_send);
        binding->events().OnEchoNamedEvent(std::move(to_send));
      }
    }
  }

  void EchoTablePayload(RequestTable payload, EchoTablePayloadCallback callback) override {
    if (payload.has_forward_to_server()) {
      EchoClientApp app;
      const std::string& forward_to_server = payload.forward_to_server();
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      payload.clear_forward_to_server();
      app.echo()->EchoTablePayload(std::move(payload),
                                   [this, &called_back, &callback](ResponseTable resp) {
                                     called_back = true;
                                     callback(std::move(resp));
                                     loop_->Quit();
                                   });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      ResponseTable resp;
      resp.set_value(payload.value());
      callback(std::move(resp));
    }
  }

  void EchoTablePayloadNoRetVal(RequestTable payload) override {
    if (payload.has_forward_to_server()) {
      std::unique_ptr<EchoClientApp> app(new EchoClientApp);
      const std::string& forward_to_server = payload.forward_to_server();
      app->echo().set_error_handler([this, forward_to_server](zx_status_t status) {
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app->Start(forward_to_server);
      app->echo().events().OnEchoTablePayloadEvent = [this](ResponseTable resp) {
        this->HandleOnTablePayloadEvent(std::move(resp));
      };
      payload.clear_forward_to_server();
      app->echo()->EchoTablePayloadNoRetVal(std::move(payload));
      client_apps_.push_back(std::move(app));
    } else {
      for (const auto& binding : bindings_.bindings()) {
        ResponseTable resp;
        resp.set_value(payload.value());
        binding->events().OnEchoTablePayloadEvent(std::move(resp));
      }
    }
  }

  void EchoTablePayloadWithError(EchoEchoTablePayloadWithErrorRequest payload,
                                 EchoTablePayloadWithErrorCallback callback) override {
    if (payload.has_forward_to_server()) {
      EchoClientApp app;
      const std::string& forward_to_server = payload.forward_to_server();
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      payload.clear_forward_to_server();
      app.echo()->EchoTablePayloadWithError(
          std::move(payload),
          [this, &called_back, &callback](Echo_EchoTablePayloadWithError_Result res) {
            called_back = true;
            callback(std::move(res));
            loop_->Quit();
          });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      Echo_EchoTablePayloadWithError_Result result;
      if (payload.result_variant() == RespondWith::ERR) {
        result.set_err(payload.result_err());
      } else {
        ResponseTable resp;
        resp.set_value(payload.value());
        result.set_response(std::move(resp));
      }
      callback(std::move(result));
    }
  }

  void EchoTableRequestComposed(
      ::fidl::test::imported::ComposedEchoTableRequestComposedRequest payload,
      EchoTableRequestComposedCallback callback) override {
    if (payload.has_forward_to_server()) {
      EchoClientApp app;
      const std::string& forward_to_server = payload.forward_to_server();
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      payload.clear_forward_to_server();
      app.echo()->EchoTableRequestComposed(
          std::move(payload), [this, &called_back, &callback](imported::SimpleStruct resp) {
            called_back = true;
            callback(std::move(resp));
            loop_->Quit();
          });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      imported::SimpleStruct resp = {.f1 = true, .f2 = payload.value()};
      callback(std::move(resp));
    }
  }

  void EchoUnionPayload(RequestUnion payload, EchoUnionPayloadCallback callback) override {
    const std::string& forward_to_server = payload.is_signed_()
                                               ? payload.signed_().forward_to_server
                                               : payload.unsigned_().forward_to_server;
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      if (payload.is_signed_()) {
        payload.signed_().forward_to_server = "";
      } else {
        payload.unsigned_().forward_to_server = "";
      }
      app.echo()->EchoUnionPayload(std::move(payload),
                                   [this, &called_back, &callback](ResponseUnion resp) {
                                     called_back = true;
                                     callback(std::move(resp));
                                     loop_->Quit();
                                   });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      ResponseUnion resp;
      if (payload.is_signed_()) {
        resp.set_signed_(payload.signed_().value);
      } else {
        resp.set_unsigned_(payload.unsigned_().value);
      }
      callback(std::move(resp));
    }
  }

  void EchoUnionPayloadWithError(EchoEchoUnionPayloadWithErrorRequest payload,
                                 EchoUnionPayloadWithErrorCallback callback) override {
    const std::string& forward_to_server = payload.is_signed_()
                                               ? payload.signed_().forward_to_server
                                               : payload.unsigned_().forward_to_server;
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      if (payload.is_signed_()) {
        payload.signed_().forward_to_server = "";
      } else {
        payload.unsigned_().forward_to_server = "";
      }
      app.echo()->EchoUnionPayloadWithError(
          std::move(payload),
          [this, &called_back, &callback](Echo_EchoUnionPayloadWithError_Result res) {
            called_back = true;
            callback(std::move(res));
            loop_->Quit();
          });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
    } else {
      const RespondWith result_variant = payload.is_signed_() ? payload.signed_().result_variant
                                                              : payload.unsigned_().result_variant;
      Echo_EchoUnionPayloadWithError_Result result;
      ResponseUnion resp;
      if (result_variant == RespondWith::ERR) {
        result.set_err(payload.is_signed_() ? payload.signed_().result_err
                                            : payload.unsigned_().result_err);
      } else {
        if (payload.is_signed_()) {
          resp.set_signed_(payload.signed_().value);
        } else {
          resp.set_unsigned_(payload.unsigned_().value);
        }
        result.set_response(std::move(resp));
      }
      callback(std::move(result));
    }
  }

  void EchoUnionPayloadNoRetVal(RequestUnion payload) override {
    const std::string& forward_to_server = payload.is_signed_()
                                               ? payload.signed_().forward_to_server
                                               : payload.unsigned_().forward_to_server;
    if (!forward_to_server.empty()) {
      std::unique_ptr<EchoClientApp> app(new EchoClientApp);
      app->echo().set_error_handler([this, forward_to_server](zx_status_t status) {
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app->Start(forward_to_server);
      app->echo().events().OnEchoUnionPayloadEvent = [this](ResponseUnion resp) {
        this->HandleOnUnionPayloadEvent(std::move(resp));
      };
      if (payload.is_signed_()) {
        payload.signed_().forward_to_server = "";
      } else {
        payload.unsigned_().forward_to_server = "";
      }
      app->echo()->EchoUnionPayloadNoRetVal(std::move(payload));
      client_apps_.push_back(std::move(app));
    } else {
      for (const auto& binding : bindings_.bindings()) {
        ResponseUnion resp;
        if (payload.is_signed_()) {
          resp.set_signed_(payload.signed_().value);
        } else {
          resp.set_unsigned_(payload.unsigned_().value);
        }
        binding->events().OnEchoUnionPayloadEvent(std::move(resp));
      }
    }
  }

  void EchoUnionResponseWithErrorComposed(
      int64_t value, bool want_absolute_value, std::string forward_to_server, uint32_t err,
      imported::WantResponse result_variant,
      EchoUnionResponseWithErrorComposedCallback callback) override {
    if (!forward_to_server.empty()) {
      EchoClientApp app;
      bool failed = false;
      app.echo().set_error_handler([this, &forward_to_server, &failed](zx_status_t status) {
        failed = true;
        loop_->Quit();
        FX_LOGS(ERROR) << "error communicating with " << forward_to_server << ": " << status;
      });
      app.Start(forward_to_server);
      bool called_back = false;
      app.echo()->EchoUnionResponseWithErrorComposed(
          value, want_absolute_value, "", err, result_variant,
          [this, &called_back,
           &callback](imported::Composed_EchoUnionResponseWithErrorComposed_Result resp) {
            called_back = true;
            callback(std::move(resp));
            loop_->Quit();
          });
      while (!called_back && !failed) {
        loop_->Run();
      }
      loop_->ResetQuit();
      return;
    }

    imported::Composed_EchoUnionResponseWithErrorComposed_Result result;
    if (result_variant == imported::WantResponse::ERR) {
      result.set_err(err);
    } else if (want_absolute_value) {
      result.set_response(
          ::fidl::test::imported::Composed_EchoUnionResponseWithErrorComposed_Response::
              WithUnsigned_(static_cast<uint64_t>(std::abs(value))));
    } else {
      result.set_response(
          ::fidl::test::imported::Composed_EchoUnionResponseWithErrorComposed_Response::WithSigned_(
              std::move(value)));
    }
    callback(std::move(result));
  }

 private:
  void HandleEchoEvent(Struct value) {
    for (const auto& binding : bindings_.bindings()) {
      Struct to_send;
      value.Clone(&to_send);
      binding->events().EchoEvent(std::move(to_send));
    }
  }
  void HandleEchoMinimalEvent() {
    for (const auto& binding : bindings_.bindings()) {
      binding->events().EchoMinimalEvent();
    }
  }
  void HandleOnEchoNamedEvent(imported::SimpleStruct value) {
    for (const auto& binding : bindings_.bindings()) {
      imported::SimpleStruct to_send;
      value.Clone(&to_send);
      binding->events().OnEchoNamedEvent(std::move(to_send));
    }
  }
  void HandleOnTablePayloadEvent(ResponseTable payload) {
    for (const auto& binding : bindings_.bindings()) {
      ResponseTable to_send;
      payload.Clone(&to_send);
      binding->events().OnEchoTablePayloadEvent(std::move(to_send));
    }
  }
  void HandleOnUnionPayloadEvent(ResponseUnion payload) {
    for (const auto& binding : bindings_.bindings()) {
      ResponseUnion to_send;
      payload.Clone(&to_send);
      binding->events().OnEchoUnionPayloadEvent(std::move(to_send));
    }
  }

  EchoPtr server_ptr;
  EchoServerApp(const EchoServerApp&) = delete;
  EchoServerApp& operator=(const EchoServerApp&) = delete;

  async::Loop* loop_;
  std::unique_ptr<sys::ComponentContext> context_;
  fidl::BindingSet<Echo> bindings_;
  std::vector<std::unique_ptr<EchoClientApp>> client_apps_;
};

}  // namespace compatibility
}  // namespace test
}  // namespace fidl

int main(int argc, const char** argv) {
  // The FIDL support lib requires async_get_default_dispatcher() to return
  // non-null.
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);

  fidl::test::compatibility::EchoServerApp app(&loop);
  loop.Run();
  return EXIT_SUCCESS;
}
