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

// ============================================================================
// This is an accompanying example code for the C++ client tutorial. Head over
// there for the full walk-through:
// https://fuchsia.dev/fuchsia-src/development/languages/fidl/tutorials/cpp/basics/client
// ============================================================================

// [START includes]
#include <fidl/fuchsia.examples/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/syslog/cpp/macros.h>
// [END includes]

// [START main]
int main(int argc, const char** argv) {
  // Connect to the |fuchsia.examples/Echo| protocol inside the component's
  // namespace. This can fail so it's wrapped in a |zx::result| and it must be
  // checked for errors.
  zx::result client_end = component::Connect<fuchsia_examples::Echo>();
  if (!client_end.is_ok()) {
    FX_LOGS(ERROR) << "Synchronous error when connecting to the |Echo| protocol: "
                   << client_end.status_string();
    return -1;
  }

  async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
  async_dispatcher_t* dispatcher = loop.dispatcher();

  // Define the event handler implementation for the client.
  //
  // The event handler delegate should be an object that implements the
  // |fidl::WireAsyncEventHandler<Echo>| virtual class, which has methods
  // corresponding to the events offered by the protocol. By default those
  // methods are no-ops.
  // [START event-handler-short]
  class EventHandler : public fidl::WireAsyncEventHandler<fuchsia_examples::Echo> {
   public:
    void OnString(fidl::WireEvent<fuchsia_examples::Echo::OnString>* event) override {
      FX_LOGS(INFO) << "(Natural types) got event: " << event->response.get();
      loop_.Quit();
    }
    // [END event-handler-short]

    // One may also override the |on_fidl_error| method, which is called
    // when the client encounters an error and is going to teardown.
    void on_fidl_error(fidl::UnbindInfo error) override { FX_LOGS(ERROR) << error; }

    explicit EventHandler(async::Loop& loop) : loop_(loop) {}

   private:
    async::Loop& loop_;
  };

  // Create an instance of the event handler.
  EventHandler event_handler(loop);

  // Create a client to the Echo protocol, passing our |event_handler| created
  // earlier. The |event_handler| must live for at least as long as the
  // |client|. The |client| holds a reference to the |event_handler| so it is a
  // bug for the |event_handler| to be destroyed before the |client|.
  // [START init-client-short]
  fidl::WireClient client(std::move(*client_end), dispatcher, &event_handler);
  // [END init-client-short]

  // Make an EchoString call, passing it a lambda to handle the result asynchronously.
  // |result| contains the method response or a transport error if applicable.
  client->EchoString("hello").ThenExactlyOnce(
      [&](fidl::WireUnownedResult<fuchsia_examples::Echo::EchoString>& result) {
        // Check if the FIDL call succeeded or not.
        if (!result.ok()) {
          // If the call failed, log the error, and crash the program.
          // Production code should do more graceful error handling depending
          // on the situation.
          FX_LOGS(ERROR) << "EchoString failed: " << result.error();
          ZX_PANIC("%s", result.error().FormatDescription().c_str());
        }
        // Dereference (->) the result object to access the response payload.
        std::string_view response = result->response.get();
        FX_LOGS(INFO) << "Got response: " << response;
        loop.Quit();
      });
  // Run the dispatch loop, until we receive a reply, in which case the callback
  // above will quit the loop, breaking us out of the |Run| function.
  loop.Run();
  loop.ResetQuit();

  // [START sync-call]
  // Make a synchronous EchoString call, which blocks until it receives the response,
  // then returns a WireResult object for the response.
  fidl::WireResult result_sync = client.sync()->EchoString("hello");
  ZX_ASSERT(result_sync.ok());
  std::string_view response = result_sync->response.get();
  FX_LOGS(INFO) << "Got synchronous response: " << response;
  // [END sync-call]

  // Make a SendString request. The resulting OnString event will be handled by
  // the event handler defined above.
  fidl::Status status_oneway = client->SendString("hi");
  // Check for any synchronous errors.
  ZX_ASSERT(status_oneway.ok());
  loop.Run();

  return 0;
}
// [END main]
