// Copyright 2016 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 "src/ledger/bin/storage/impl/ledger_storage_impl.h"

#include <dirent.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/callback/scoped_callback.h>
#include <lib/callback/trace_callback.h>
#include <lib/fit/function.h>

#include <algorithm>
#include <iterator>
#include <string>

#include "peridot/lib/base64url/base64url.h"
#include "src/ledger/bin/filesystem/directory_reader.h"
#include "src/ledger/bin/storage/impl/page_storage_impl.h"
#include "src/ledger/bin/storage/public/constants.h"
#include "src/lib/files/directory.h"
#include "src/lib/files/path.h"
#include "src/lib/files/scoped_temp_dir.h"
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/strings/concatenate.h"

namespace storage {

namespace {

constexpr fxl::StringView kStagingDirName = "staging";

// Encodes opaque bytes in a way that is usable as a directory name.
std::string GetDirectoryName(fxl::StringView bytes) {
  return base64url::Base64UrlEncode(bytes);
}

// Decodes opaque bytes used as a directory names into an id. This is the
// opposite transformation of GetDirectoryName.
std::string GetId(fxl::StringView bytes) {
  std::string decoded;
  bool result = base64url::Base64UrlDecode(bytes, &decoded);
  FXL_DCHECK(result);
  return decoded;
}

}  // namespace

LedgerStorageImpl::LedgerStorageImpl(
    ledger::Environment* environment,
    encryption::EncryptionService* encryption_service, DbFactory* db_factory,
    ledger::DetachedPath content_dir)
    : environment_(environment),
      encryption_service_(encryption_service),
      db_factory_(db_factory),
      storage_dir_(std::move(content_dir)),
      staging_dir_(storage_dir_.SubPath(kStagingDirName)),
      weak_factory_(this) {}

LedgerStorageImpl::~LedgerStorageImpl() {}

Status LedgerStorageImpl::Init() {
  if (!files::CreateDirectoryAt(storage_dir_.root_fd(), storage_dir_.path())) {
    FXL_LOG(ERROR) << "Failed to create the storage directory in "
                   << storage_dir_.path();
    return Status::INTERNAL_ERROR;
  }
  return Status::OK;
}

void LedgerStorageImpl::CreatePageStorage(
    PageId page_id,
    fit::function<void(Status, std::unique_ptr<PageStorage>)> callback) {
  auto timed_callback = TRACE_CALLBACK(std::move(callback), "ledger",
                                       "ledger_storage_create_page_storage");
  auto page_path = GetPathFor(page_id);
  GetOrCreateDb(std::move(page_path), std::move(page_id),
                DbFactory::OnDbNotFound::CREATE, std::move(timed_callback));
}

void LedgerStorageImpl::GetPageStorage(
    PageId page_id,
    fit::function<void(Status, std::unique_ptr<PageStorage>)> callback) {
  auto timed_callback = TRACE_CALLBACK(std::move(callback), "ledger",
                                       "ledger_storage_get_page_storage");
  auto page_path = GetPathFor(page_id);
  GetOrCreateDb(std::move(page_path), std::move(page_id),
                DbFactory::OnDbNotFound::RETURN, std::move(timed_callback));
}

void LedgerStorageImpl::DeletePageStorage(
    PageIdView page_id, fit::function<void(Status)> callback) {
  auto timed_callback = TRACE_CALLBACK(std::move(callback), "ledger",
                                       "ledger_storage_delete_page_storage");
  ledger::DetachedPath path = GetPathFor(page_id);
  // |final_callback| will be called from the I/O loop and call the original
  // |callback| in the main one. The main loop outlives the I/O one, so it's
  // safe to capture environment_->dispatcher() here.
  auto final_callback = [dispatcher = environment_->dispatcher(),
                         callback =
                             std::move(timed_callback)](Status status) mutable {
    // Call the callback in the main thread.
    async::PostTask(dispatcher, [status, callback = std::move(callback)] {
      callback(status);
    });
  };

  async::PostTask(
      environment_->io_dispatcher(),
      [path = std::move(path), staging_dir = staging_dir_,
       callback = std::move(final_callback)]() mutable {
        if (!files::IsDirectoryAt(path.root_fd(), path.path())) {
          callback(Status::PAGE_NOT_FOUND);
          return;
        }
        files::ScopedTempDirAt tmp_directory(staging_dir.root_fd(),
                                             staging_dir.path());
        std::string destination = tmp_directory.path() + "/graveyard";

        // <storage_dir_>/<base64(page)> becomes
        // <storage_dir_>/staging/<random_temporary_name>/graveyard/<base64(page)>
        if (renameat(path.root_fd(), path.path().c_str(),
                     tmp_directory.root_fd(), destination.c_str()) != 0) {
          FXL_LOG(ERROR) << "Unable to move local page storage to "
                         << destination << ". Error: " << strerror(errno);
          callback(Status::IO_ERROR);
          return;
        }

        if (!files::DeletePathAt(tmp_directory.root_fd(), destination, true)) {
          FXL_LOG(ERROR) << "Unable to delete local staging storage at: "
                         << destination;
          callback(Status::IO_ERROR);
          return;
        }
        callback(Status::OK);
      });
}

std::vector<PageId> LedgerStorageImpl::ListLocalPages() {
  std::vector<PageId> local_pages;
  ledger::GetDirectoryEntries(
      storage_dir_, [&local_pages](fxl::StringView encoded_page_id) {
        local_pages.emplace_back(GetId(encoded_page_id));
        return true;
      });
  return local_pages;
}

void LedgerStorageImpl::InitializePageStorage(
    PageId page_id, std::unique_ptr<Db> db,
    fit::function<void(Status, std::unique_ptr<PageStorage>)> callback) {
  auto storage = std::make_unique<PageStorageImpl>(
      environment_, encryption_service_, std::move(db), std::move(page_id));
  PageStorageImpl* storage_ptr = storage.get();
  storage_in_initialization_[storage_ptr] = std::move(storage);
  storage_ptr->Init([this, callback = std::move(callback),
                     storage_ptr](Status status) mutable {
    std::unique_ptr<PageStorage> storage =
        std::move(storage_in_initialization_[storage_ptr]);
    storage_in_initialization_.erase(storage_ptr);

    if (status != Status::OK) {
      FXL_LOG(ERROR) << "Failed to initialize PageStorage. Status: " << status;
      callback(status, nullptr);
      return;
    }
    callback(Status::OK, std::move(storage));
  });
}

void LedgerStorageImpl::GetOrCreateDb(
    ledger::DetachedPath path, PageId page_id,
    DbFactory::OnDbNotFound on_db_not_found,
    fit::function<void(Status, std::unique_ptr<PageStorage>)> callback) {
  db_factory_->GetOrCreateDb(
      std::move(path), on_db_not_found,
      callback::MakeScoped(
          weak_factory_.GetWeakPtr(),
          [this, page_id = std::move(page_id), callback = std::move(callback)](
              Status status, std::unique_ptr<Db> db) mutable {
            if (status != Status::OK) {
              callback(status, nullptr);
              return;
            }
            InitializePageStorage(std::move(page_id), std::move(db),
                                  std::move(callback));
          }));
}

ledger::DetachedPath LedgerStorageImpl::GetPathFor(PageIdView page_id) {
  FXL_DCHECK(!page_id.empty());
  return storage_dir_.SubPath(GetDirectoryName(page_id));
}

}  // namespace storage
