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

// [START imports]
#include <fidl/examples.routing.echo/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/component/outgoing/cpp/outgoing_directory.h>
#include <lib/inspect/component/cpp/component.h>
#include <lib/syslog/global.h>
// [END imports]

// [START handler]
struct EchoConnectionStats {
  inspect::UintProperty bytes_processed;
  inspect::UintProperty total_requests;
};

// Handler for incoming FIDL protocol requests
class EchoImplementation : public fidl::Server<examples_routing_echo::Echo> {
public:
  // The handler for `examples.routing.echo/Echo.EchoString` requests.
  //
  // Replies back to the caller with the original request value.
  void EchoString(EchoStringRequest &request,
                  EchoStringCompleter::Sync &completer) override {
    // Increment connection stats on each request
    stats_->total_requests.Add(1);
    stats_->bytes_processed.Add(request.value()->size());
    completer.Reply({{request.value()}});
  }

  // Called when the FIDL connection is torn down.
  void OnUnbound(fidl::UnbindInfo info,
                 fidl::ServerEnd<examples_routing_echo::Echo> server_end) {
    if (info.is_user_initiated()) {
      return;
    }
    if (info.is_peer_closed()) {
      // The peer (the client) closed their endpoint.
      FX_LOG(DEBUG, "echo_server", "Client disconnected.");
    } else {
      // Treat other unbind causes as errors.
      FX_LOGF(ERROR, "echo_server", "Server error: %s", info.status_string());
    }
  }

  std::unique_ptr<EchoConnectionStats> stats_;
};
// [END handler]

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

  // Initialize inspect
  inspect::ComponentInspector inspector(loop.dispatcher(), {});
  inspector.Health().StartingUp();

  // [START echo_instance]
  // Serve the Echo protocol
  std::unique_ptr<EchoImplementation> echo_instance =
      std::make_unique<EchoImplementation>();
  // [END echo_instance]
  zx::result result = outgoing.AddProtocol<examples_routing_echo::Echo>(
      std::move(echo_instance));
  if (result.is_error()) {
    FX_LOGF(ERROR, "echo_server", "Failed to add Echo protocol: %s",
            result.status_string());
    return -1;
  }

  result = outgoing.ServeFromStartupInfo();
  if (result.is_error()) {
    FX_LOGF(ERROR, "echo_server", "Failed to serve outgoing directory: %s",
            result.status_string());
    return -1;
  }

  // [START add_properties]
  // Create request tracking properties
  inspect::Node &root_node = inspector.root();
  auto total_requests = root_node.CreateUint("total_requests", 0);
  auto bytes_processed = root_node.CreateUint("bytes_processed", 0);
  echo_instance->stats_ =
      std::make_unique<EchoConnectionStats>(EchoConnectionStats{
          std::move(bytes_processed),
          std::move(total_requests),
      });
  // [END add_properties]

  // Component is serving and ready to handle incoming requests
  inspector.Health().Ok();

  return loop.Run();
}
