// Copyright 2020 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/fuchsia.examples/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/sys/component/llcpp/handlers.h>
#include <lib/sys/component/llcpp/outgoing_directory.h>

#include <iostream>

// An implementation of the Echo protocol. Protocols are implemented in LLCPP by
// creating a subclass of the ::Interface class for the protocol.
class EchoImpl final : public fidl::WireServer<fuchsia_examples::Echo> {
 public:
  // Bind this implementation to a channel.
  EchoImpl(bool reverse, async_dispatcher_t* dispatcher,
           fidl::ServerEnd<fuchsia_examples::Echo> request)
      : reverse_(reverse),
        binding_(fidl::BindServer(dispatcher, std::move(request), this,
                                  // This is a fidl::OnUnboundFn<EchoImpl>.
                                  [this](EchoImpl* impl, fidl::UnbindInfo info,
                                         fidl::ServerEnd<fuchsia_examples::Echo> server_end) {
                                    if (info.is_peer_closed()) {
                                      std::cout << "Client disconnected" << std::endl;
                                    } else if (!info.is_user_initiated()) {
                                      std::cerr << "server error: " << info << std::endl;
                                    }
                                    delete this;
                                  })) {}

  // Handle a SendString request by sending on OnString event with the request value. For
  // fire and forget methods, the completer can be used to close the channel with an epitaph.
  void SendString(SendStringRequestView request, SendStringCompleter::Sync& completer) override {}

  // Handle an EchoString request by responding with the request value. For two-way
  // methods, the completer is also used to send a response.
  void EchoString(EchoStringRequestView request, EchoStringCompleter::Sync& completer) override {
    std::string value(request->value.get());
    std::cout << "Got echo request: " << value << std::endl;
    if (reverse_) {
      std::reverse(value.begin(), value.end());
    }
    std::cout << "Sending response: " << value << std::endl;
    auto reply = fidl::StringView::FromExternal(value);
    completer.Reply(reply);
  }

 private:
  const bool reverse_;
  fidl::ServerBindingRef<fuchsia_examples::Echo> binding_;
};

int main(int argc, const char** argv) {
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  auto outgoing = component::OutgoingDirectory::Create(loop.dispatcher());

  component::ServiceHandler handler;
  fuchsia_examples::EchoService::Handler my_service(&handler);

  // Example of serving members of a service instance.
  auto add_regular_result = my_service.add_regular_echo(
      [&loop](fidl::ServerEnd<fuchsia_examples::Echo> request_channel) -> void {
        new EchoImpl(false, loop.dispatcher(), std::move(request_channel));
      });
  ZX_ASSERT(add_regular_result.is_ok());

  auto add_reversed_result = my_service.add_reversed_echo(
      [&loop](fidl::ServerEnd<fuchsia_examples::Echo> request_channel) -> void {
        new EchoImpl(true, loop.dispatcher(), std::move(request_channel));
      });
  ZX_ASSERT(add_reversed_result.is_ok());

  // Example of serving an instance of "EchoService".
  auto result = outgoing.AddService<fuchsia_examples::EchoService>(std::move(handler));
  if (result.is_error()) {
    return result.status_value();
  }
  result = outgoing.ServeFromStartupInfo();
  if (result.is_error()) {
    return result.status_value();
  }

  std::cout << "Running echo server" << std::endl;
  loop.Run();
  return 0;
}
