// Copyright 2017 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 "peridot/bin/cloud_provider_firestore/app/cloud_provider_impl.h"

#include <utility>

#include <lib/callback/scoped_callback.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/strings/concatenate.h>
#include <lib/fxl/strings/string_view.h>

#include "peridot/bin/cloud_provider_firestore/app/credentials_provider_impl.h"
#include "peridot/bin/cloud_provider_firestore/app/grpc_status.h"
#include "peridot/bin/cloud_provider_firestore/firestore/encoding.h"
#include "peridot/bin/ledger/app/serialization_version.h"
#include "peridot/lib/convert/convert.h"

namespace cloud_provider_firestore {

constexpr char kSeparator[] = "/";
constexpr char kUsersCollection[] = "users";
constexpr char kVersionsCollection[] = "versions";
constexpr char kPageCollection[] = "pages";
constexpr char kNamespaceCollection[] = "namespaces";
constexpr char kExistsKey[] = "exists";

std::string GetUserPath(fxl::StringView root_path, fxl::StringView user_id) {
  return fxl::Concatenate({
      root_path,
      kSeparator,
      kUsersCollection,
      kSeparator,
      user_id,
  });
}

std::string GetVersionPath(fxl::StringView user_path) {
  return fxl::Concatenate({
      user_path,
      kSeparator,
      kVersionsCollection,
      kSeparator,
      ledger::kSerializationVersion,
  });
}

std::string GetNamespacePath(fxl::StringView version_path,
                             fxl::StringView namespace_id) {
  std::string encoded_namespace_id = EncodeKey(namespace_id);
  return fxl::Concatenate({version_path, kSeparator, kNamespaceCollection,
                           kSeparator, encoded_namespace_id});
}

std::string GetPagePath(fxl::StringView namespace_path,
                        fxl::StringView page_id) {
  std::string encoded_page_id = EncodeKey(page_id);
  return fxl::Concatenate({namespace_path, kSeparator, kPageCollection,
                           kSeparator, encoded_page_id});
}

CloudProviderImpl::CloudProviderImpl(
    rng::Random* random, std::string user_id,
    std::unique_ptr<firebase_auth::FirebaseAuth> firebase_auth,
    std::unique_ptr<FirestoreService> firestore_service,
    fidl::InterfaceRequest<cloud_provider::CloudProvider> request)
    : random_(random),
      user_id_(std::move(user_id)),
      firestore_service_(std::move(firestore_service)),
      binding_(this, std::move(request)),
      weak_ptr_factory_(this) {
  // The class shuts down when the client connection is disconnected.
  binding_.set_error_handler(
      [this](zx_status_t status) { ShutDownAndReportEmpty(); });
  // The class also shuts down when the auth provider is disconnected.
  firebase_auth->set_error_handler([this] {
    FXL_LOG(ERROR) << "Lost connection to the token provider, "
                   << "shutting down the cloud provider.";
    ShutDownAndReportEmpty();
  });

  credentials_provider_ =
      std::make_unique<CredentialsProviderImpl>(std::move(firebase_auth));
}

CloudProviderImpl::~CloudProviderImpl() {}

void CloudProviderImpl::ShutDownAndReportEmpty() {
  if (binding_.is_bound()) {
    binding_.Unbind();
  }

  fit::closure shut_down = [this] {
    firestore_service_->ShutDown([this] {
      if (on_empty_) {
        on_empty_();
      }
    });
  };

  if (pending_placeholder_requests_.empty()) {
    shut_down();
    return;
  }

  pending_placeholder_requests_.set_on_empty(std::move(shut_down));
}

void CloudProviderImpl::ScopedGetCredentials(
    fit::function<void(std::shared_ptr<grpc::CallCredentials>)> callback) {
  credentials_provider_->GetCredentials(callback::MakeScoped(
      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void CloudProviderImpl::GetDeviceSet(
    fidl::InterfaceRequest<cloud_provider::DeviceSet> device_set,
    GetDeviceSetCallback callback) {
  const std::string user_path =
      GetUserPath(firestore_service_->GetRootPath(), user_id_);
  const std::string version_path = GetVersionPath(user_path);
  device_sets_.emplace(version_path, credentials_provider_.get(),
                       firestore_service_.get(), std::move(device_set));
  callback(cloud_provider::Status::OK);

  // Create a placeholder document for the root of the serialization version.
  CreatePlaceholderDocument(user_path, kVersionsCollection,
                            ledger::kSerializationVersion.ToString());
}

void CloudProviderImpl::GetPageCloud(
    std::vector<uint8_t> app_id, std::vector<uint8_t> page_id,
    fidl::InterfaceRequest<cloud_provider::PageCloud> page_cloud,
    GetPageCloudCallback callback) {
  const std::string user_path =
      GetUserPath(firestore_service_->GetRootPath(), user_id_);
  const std::string version_path = GetVersionPath(user_path);
  const std::string app_id_str = convert::ToString(app_id);
  const std::string namespace_path = GetNamespacePath(version_path, app_id_str);
  const std::string page_id_str = convert::ToString(page_id);
  const std::string page_path = GetPagePath(namespace_path, page_id_str);
  page_clouds_.emplace(page_path, random_, credentials_provider_.get(),
                       firestore_service_.get(), std::move(page_cloud));
  callback(cloud_provider::Status::OK);

  // Create a placeholder document for the root of the serialization version.
  CreatePlaceholderDocument(user_path, kVersionsCollection,
                            ledger::kSerializationVersion.ToString());
  // Create a placeholder document for the root of the app namespace.
  CreatePlaceholderDocument(version_path, kNamespaceCollection,
                            EncodeKey(app_id_str));
  // Create a placeholder document for the root of the page.
  CreatePlaceholderDocument(namespace_path, kPageCollection,
                            EncodeKey(page_id_str));
}

void CloudProviderImpl::CreatePlaceholderDocument(
    std::string parent_document_path, std::string collection_id,
    std::string document_id) {
  auto request = google::firestore::v1beta1::CreateDocumentRequest();
  request.set_parent(std::move(parent_document_path));
  request.set_collection_id(std::move(collection_id));
  request.set_document_id(std::move(document_id));
  google::firestore::v1beta1::Value exists;
  exists.set_boolean_value(true);
  (*(request.mutable_document()->mutable_fields()))[kExistsKey] = exists;

  // Create an object that tracks the request in progress, so that we don't shut
  // down between requesting and receiving the credentials (see
  // ShutDownAndReportEmoty()). The value |true| is not meaningful.
  auto pending_request_marker = pending_placeholder_requests_.Manage(true);
  ScopedGetCredentials(
      [this, request = std::move(request),
       pending_request_marker =
           std::move(pending_request_marker)](auto call_credentials) mutable {
        firestore_service_->CreateDocument(
            std::move(request), std::move(call_credentials),
            [](auto status, auto result) {
              if (status.error_code() != grpc::OK &&
                  status.error_code() != grpc::ALREADY_EXISTS) {
                LogGrpcRequestError(status);
              }
            });
      });
}

}  // namespace cloud_provider_firestore
