// Copyright 2019 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/llcpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fidl-async/cpp/bind.h>
#include <lib/fidl/cpp/interface_request.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";

namespace fidl {
namespace test {
namespace compatibility {

class EchoClientApp {
 public:
  EchoClientApp(::fidl::StringView server_url)
      : context_(sys::ComponentContext::Create()),
        client_(Echo::SyncClient(ConnectTo(server_url))) {}

  ::fidl::DecodeResult<Echo::EchoStructResponse> EchoStruct(
      ::fidl::BytePart request_buffer, Struct value,
      ::fidl::StringView forward_to_server, ::fidl::BytePart response_buffer,
      Struct* out_value) {
    return client_.EchoStruct(std::move(request_buffer), std::move(value),
                              forward_to_server, std::move(response_buffer),
                              out_value);
  }

  zx_status_t EchoStructNoRetVal(Struct value,
                                 ::fidl::StringView forward_to_server,
                                 Echo::EventHandlers event_handlers) {
    auto status =
        client_.EchoStructNoRetVal(std::move(value), forward_to_server);
    if (status != ZX_OK) {
      return status;
    }
    return client_.HandleEvents(std::move(event_handlers));
  }

  ::fidl::DecodeResult<Echo::EchoArraysResponse> EchoArrays(
      ::fidl::BytePart request_buffer, ArraysStruct value,
      ::fidl::StringView forward_to_server, ::fidl::BytePart response_buffer,
      ArraysStruct* out_value) {
    return client_.EchoArrays(std::move(request_buffer), std::move(value),
                              forward_to_server, std::move(response_buffer),
                              out_value);
  }

  ::fidl::DecodeResult<Echo::EchoVectorsResponse> EchoVectors(
      ::fidl::BytePart request_buffer, VectorsStruct value,
      ::fidl::StringView forward_to_server, ::fidl::BytePart response_buffer,
      VectorsStruct* out_value) {
    return client_.EchoVectors(std::move(request_buffer), std::move(value),
                               forward_to_server, std::move(response_buffer),
                               out_value);
  }

  ::fidl::DecodeResult<Echo::EchoTableResponse> EchoTable(
      ::fidl::BytePart request_buffer, AllTypesTable value,
      ::fidl::StringView forward_to_server, ::fidl::BytePart response_buffer,
      AllTypesTable* out_value) {
    return client_.EchoTable(std::move(request_buffer), std::move(value),
                             forward_to_server, std::move(response_buffer),
                             out_value);
  }

  ::fidl::DecodeResult<Echo::EchoXunionsResponse> EchoXunions(
      ::fidl::BytePart request_buffer, ::fidl::VectorView<AllTypesXunion> value,
      ::fidl::StringView forward_to_server, ::fidl::BytePart response_buffer,
      ::fidl::VectorView<AllTypesXunion>* out_value) {
    return client_.EchoXunions(std::move(request_buffer), std::move(value),
                               forward_to_server, std::move(response_buffer),
                               out_value);
  }

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

 private:
  // Called once upon construction to launch and connect to the server.
  zx::channel ConnectTo(::fidl::StringView 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());

    zx::channel server_end, client_end;
    ZX_ASSERT(zx::channel::create(0, &client_end, &server_end) == ZX_OK);
    ZX_ASSERT(echo_provider_->Connect(kEchoInterfaceName,
                                      std::move(server_end)) == ZX_OK);

    return client_end;
  }

  std::unique_ptr<sys::ComponentContext> context_;
  std::shared_ptr<sys::ServiceDirectory> echo_provider_;
  fuchsia::sys::ComponentControllerPtr controller_;
  Echo::SyncClient client_;
};

class EchoConnection final : public Echo::Interface {
 public:
  explicit EchoConnection(zx::unowned_channel channel) : channel_(channel) {}

  void EchoStruct(Struct value, ::fidl::StringView forward_to_server,
                  EchoStructCompleter::Sync completer) override {
    if (forward_to_server.empty()) {
      completer.Reply(std::move(value));
    } else {
      std::vector<uint8_t> request_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
      std::vector<uint8_t> response_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
      EchoClientApp app(forward_to_server);
      Struct out_value;
      auto result = app.EchoStruct(
          ::fidl::BytePart(&request_buffer[0],
                           static_cast<uint32_t>(request_buffer.size())),
          std::move(value), ::fidl::StringView{0, ""},
          ::fidl::BytePart(&response_buffer[0],
                           static_cast<uint32_t>(response_buffer.size())),
          &out_value);
      ZX_ASSERT_MSG(result.status == ZX_OK, "Forwarding failed: %s",
                    result.error);
      completer.Reply(std::move(out_value));
    }
  }

  void EchoStructNoRetVal(
      Struct value, ::fidl::StringView forward_to_server,
      EchoStructNoRetValCompleter::Sync completer) override {
    if (forward_to_server.empty()) {
      auto status = Echo::SendEchoEventEvent(zx::unowned_channel(channel_),
                                             std::move(value));
      ZX_ASSERT_MSG(status == ZX_OK, "Replying with event failed: %s",
                    zx_status_get_string(status));
    } else {
      EchoClientApp app(forward_to_server);
      zx_status_t status = app.EchoStructNoRetVal(
          std::move(value), ::fidl::StringView{0, ""},
          Echo::EventHandlers{.echo_event =
                                  [&](Struct value) {
                                    return Echo::SendEchoEventEvent(
                                        zx::unowned_channel(channel_),
                                        std::move(value));
                                  },
                              .unknown =
                                  [] {
                                    ZX_PANIC("Received unexpected event");
                                    return ZX_ERR_INVALID_ARGS;
                                  }});
      ZX_ASSERT_MSG(status == ZX_OK, "Replying with event failed: %s",
                    zx_status_get_string(status));
    }
  }

  void EchoArrays(ArraysStruct value, ::fidl::StringView forward_to_server,
                  EchoArraysCompleter::Sync completer) override {
    if (forward_to_server.empty()) {
      completer.Reply(std::move(value));
    } else {
      std::vector<uint8_t> request_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
      std::vector<uint8_t> response_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
      EchoClientApp app(forward_to_server);
      ArraysStruct out_value;
      auto result = app.EchoArrays(
          ::fidl::BytePart(&request_buffer[0],
                           static_cast<uint32_t>(request_buffer.size())),
          std::move(value), ::fidl::StringView{0, ""},
          ::fidl::BytePart(&response_buffer[0],
                           static_cast<uint32_t>(response_buffer.size())),
          &out_value);
      ZX_ASSERT_MSG(result.status == ZX_OK, "Forwarding failed: %s",
                    result.error);
      completer.Reply(std::move(out_value));
    }
  }

  void EchoVectors(VectorsStruct value, ::fidl::StringView forward_to_server,
                   EchoVectorsCompleter::Sync completer) override {
    if (forward_to_server.empty()) {
      completer.Reply(std::move(value));
    } else {
      std::vector<uint8_t> request_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
      std::vector<uint8_t> response_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
      EchoClientApp app(forward_to_server);
      VectorsStruct out_value;
      auto result = app.EchoVectors(
          ::fidl::BytePart(&request_buffer[0],
                           static_cast<uint32_t>(request_buffer.size())),
          std::move(value), ::fidl::StringView{0, ""},
          ::fidl::BytePart(&response_buffer[0],
                           static_cast<uint32_t>(response_buffer.size())),
          &out_value);
      ZX_ASSERT_MSG(result.status == ZX_OK, "Forwarding failed: %s",
                    result.error);
      completer.Reply(std::move(out_value));
    }
  }

  void EchoTable(AllTypesTable value, ::fidl::StringView forward_to_server,
                 EchoTableCompleter::Sync completer) override {
    if (forward_to_server.empty()) {
      completer.Reply(std::move(value));
    } else {
      std::vector<uint8_t> request_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
      std::vector<uint8_t> response_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
      EchoClientApp app(forward_to_server);
      AllTypesTable out_value;
      auto result = app.EchoTable(
          ::fidl::BytePart(&request_buffer[0],
                           static_cast<uint32_t>(request_buffer.size())),
          std::move(value), ::fidl::StringView{0, ""},
          ::fidl::BytePart(&response_buffer[0],
                           static_cast<uint32_t>(response_buffer.size())),
          &out_value);
      ZX_ASSERT_MSG(result.status == ZX_OK, "Forwarding failed: %s",
                    result.error);
      completer.Reply(std::move(out_value));
    }
  }

  void EchoXunions(fidl::VectorView<AllTypesXunion> value,
                   ::fidl::StringView forward_to_server,
                   EchoXunionsCompleter::Sync completer) override {
    if (forward_to_server.empty()) {
      completer.Reply(std::move(value));
    } else {
      std::vector<uint8_t> request_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
      std::vector<uint8_t> response_buffer(ZX_CHANNEL_MAX_MSG_BYTES);
      EchoClientApp app(forward_to_server);
      fidl::VectorView<AllTypesXunion> out_value;
      auto result = app.EchoXunions(
          ::fidl::BytePart(&request_buffer[0],
                           static_cast<uint32_t>(request_buffer.size())),
          std::move(value), ::fidl::StringView{0, ""},
          ::fidl::BytePart(&response_buffer[0],
                           static_cast<uint32_t>(response_buffer.size())),
          &out_value);
      ZX_ASSERT_MSG(result.status == ZX_OK, "Forwarding failed: %s",
                    result.error);
      completer.Reply(std::move(out_value));
    }
  }

 private:
  zx::unowned_channel channel_;
};

}  // 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(&kAsyncLoopConfigAttachToThread);
  auto context = sys::ComponentContext::Create();
  std::vector<std::unique_ptr<fidl::test::compatibility::EchoConnection>>
      connections;

  context->outgoing()->AddPublicService(
      std::make_unique<vfs::Service>([&](zx::channel request,
                                         async_dispatcher_t* dispatcher) {
        auto conn = std::make_unique<fidl::test::compatibility::EchoConnection>(
            zx::unowned_channel(request));
        ZX_ASSERT(fidl::Bind(dispatcher, std::move(request), conn.get()) ==
                  ZX_OK);
        connections.push_back(std::move(conn));
      }),
      kEchoInterfaceName);

  loop.Run();
  return EXIT_SUCCESS;
}
