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

#ifndef PERIDOT_LIB_LEDGER_CLIENT_PROMISE_H_
#define PERIDOT_LIB_LEDGER_CLIENT_PROMISE_H_

#include <fuchsia/ledger/cpp/fidl.h>
#include <lib/fit/bridge.h>
#include <lib/fit/promise.h>

#include "peridot/lib/fidl/array_to_string.h"  // for to_string(), to_array()
#include "src/lib/fxl/logging.h"

namespace modular {

// These wrapper functions wrap fuchsia.ledger APIs such that they return
// a fit::promise<> representing the result of the call. They are useful to
// incorporate into tasks themselves expressed as fit::promises.
//
// The wrapper classes act as namespaces for static methods. For a given api
// (such as fuchsia.ledger.Page), the wrapper class is called PagePromise, and
// each method has the same signature as that in fuchsia::ledger::Page, with the
// addition that the first parameter is always a fuchsia::ledger::Page* and the
// last parameter (the result callback) is omitted.
//
// Note that these wrapper methods IMMEDIATELY call the underlying FIDL
// function (meaning that a message is dispatched immediately on the underlying
// channel). The returned promise will block until a response message is
// received.
//
// EXAMPLE
//
//   auto p = fit::make_promise([snapshot = page_snapshot_ptr.get()] () {
//     return PageSnapshotPromise::GetInline(snapshot, key);
//   }).and_then([] (const std::vector<uint8_t> bytes) {
//     // Decode and use |bytes|.
//   });

// fit::promise wrapper functions for fuchsia.ledger.PageSnspahot.
//
// These methods match the signatures in fuchsia.ledger.PageSnapshot with the
// exception that the first parameter is always a
// fuchsia::ledger::PageSnapshot*.
class PageSnapshotPromise {
 public:
  // fit::promise wrapper function for PageSnapshot.GetInline().
  //
  // Falls back to PageSnapshot::Get() if the value is too large.
  // TODO(thatguy): Implement the fallback.
  static fit::promise<std::unique_ptr<std::vector<uint8_t>>> GetInline(
      fuchsia::ledger::PageSnapshot* snapshot, std::string key) {
    fit::bridge<std::unique_ptr<std::vector<uint8_t>>> bridge;
    snapshot->GetInline(
        to_array(key),
        [completer = std::move(bridge.completer)](
            fuchsia::ledger::PageSnapshot_GetInline_Result result) mutable {
          if (result.is_response()) {
            completer.complete_ok(std::make_unique<std::vector<uint8_t>>(
                std::move(result.response().value.value)));
            return;
          }
          switch (result.err()) {
            case fuchsia::ledger::Error::KEY_NOT_FOUND:
              completer.complete_ok(nullptr);
              return;
            case fuchsia::ledger::Error::NEEDS_FETCH:
            case fuchsia::ledger::Error::NETWORK_ERROR:
              FXL_LOG(ERROR) << "PageSnapshotPromise::GetInline() failed with "
                             << fidl::ToUnderlying(result.err());
              completer.complete_error();
          }
        });
    return bridge.consumer.promise();
  }
};

}  // namespace modular

#endif  // PERIDOT_LIB_LEDGER_CLIENT_PROMISE_H_
