// 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/ledger/cloud_sync/impl/testing/test_page_storage.h"

#include <memory>
#include <set>
#include <utility>
#include <vector>

#include <lib/async/cpp/task.h>
#include <lib/callback/capture.h>
#include <lib/fit/function.h>
#include <lib/fsl/socket/strings.h>

#include "peridot/bin/ledger/cloud_sync/impl/testing/test_commit.h"
#include "peridot/bin/ledger/storage/public/page_storage.h"
#include "peridot/bin/ledger/storage/testing/page_storage_empty_impl.h"

namespace cloud_sync {
TestPageStorage::TestPageStorage(async_dispatcher_t* dispatcher)
    : dispatcher_(dispatcher) {}

std::unique_ptr<TestCommit> TestPageStorage::NewCommit(std::string id,
                                                       std::string content,
                                                       bool unsynced) {
  auto commit = std::make_unique<TestCommit>(std::move(id), std::move(content));
  if (unsynced) {
    unsynced_commits_to_return.push_back(commit->Clone());
  }
  return commit;
}

storage::PageId TestPageStorage::GetId() { return page_id_to_return; }

void TestPageStorage::SetSyncDelegate(
    storage::PageSyncDelegate* page_sync_delegate) {
  page_sync_delegate_ = page_sync_delegate;
}

void TestPageStorage::GetHeadCommitIds(
    fit::function<void(storage::Status, std::vector<storage::CommitId>)>
        callback) {
  size_t returned_head_count = head_count;
  auto confirm = [returned_head_count, callback = std::move(callback)] {
    // Current tests only rely on the number of heads, not on the actual
    // ids.
    callback(storage::Status::OK,
             std::vector<storage::CommitId>(returned_head_count));
  };
  if (should_delay_get_head_commit_ids) {
    delayed_get_head_commit_ids.emplace_back(std::move(confirm));
    return;
  }

  async::PostTask(dispatcher_, std::move(confirm));
}

void TestPageStorage::GetCommit(
    storage::CommitIdView commit_id,
    fit::function<void(storage::Status, std::unique_ptr<const storage::Commit>)>
        callback) {
  if (should_fail_get_commit) {
    async::PostTask(dispatcher_, [callback = std::move(callback)] {
      callback(storage::Status::IO_ERROR, nullptr);
    });
    return;
  }

  async::PostTask(dispatcher_, [this, commit_id = commit_id.ToString(),
                                callback = std::move(callback)] {
    callback(storage::Status::OK, std::move(new_commits_to_return[commit_id]));
  });
  new_commits_to_return.erase(commit_id.ToString());
}

void TestPageStorage::AddCommitsFromSync(
    std::vector<PageStorage::CommitIdAndBytes> ids_and_bytes,
    storage::ChangeSource /*source*/,
    fit::function<void(storage::Status, std::vector<storage::CommitId>)>
        callback) {
  add_commits_from_sync_calls++;

  if (should_fail_add_commit_from_sync) {
    async::PostTask(dispatcher_, [callback = std::move(callback)]() {
      callback(storage::Status::IO_ERROR, {});
    });
    return;
  }

  fit::closure confirm = [this, ids_and_bytes = std::move(ids_and_bytes),
                          callback = std::move(callback)]() mutable {
    for (auto& commit : ids_and_bytes) {
      received_commits[commit.id] = std::move(commit.bytes);
      unsynced_commits_to_return.erase(
          std::remove_if(
              unsynced_commits_to_return.begin(),
              unsynced_commits_to_return.end(),
              [commit_id = std::move(commit.id)](
                  const std::unique_ptr<const storage::Commit>& commit) {
                return commit->GetId() == commit_id;
              }),
          unsynced_commits_to_return.end());
    }
    async::PostTask(dispatcher_, [callback = std::move(callback)] {
      callback(storage::Status::OK, {});
    });
  };
  if (should_delay_add_commit_confirmation) {
    delayed_add_commit_confirmations.push_back(std::move(confirm));
    return;
  }
  async::PostTask(dispatcher_, std::move(confirm));
}

void TestPageStorage::GetUnsyncedPieces(
    fit::function<void(storage::Status, std::vector<storage::ObjectIdentifier>)>
        callback) {
  async::PostTask(dispatcher_, [callback = std::move(callback)] {
    callback(storage::Status::OK, std::vector<storage::ObjectIdentifier>());
  });
}

storage::Status TestPageStorage::AddCommitWatcher(
    storage::CommitWatcher* watcher) {
  watcher_ = watcher;
  watcher_set = true;
  return storage::Status::OK;
}

storage::Status TestPageStorage::RemoveCommitWatcher(
    storage::CommitWatcher* /*watcher*/) {
  watcher_removed = true;
  return storage::Status::OK;
}

void TestPageStorage::GetUnsyncedCommits(
    fit::function<void(storage::Status,
                       std::vector<std::unique_ptr<const storage::Commit>>)>
        callback) {
  if (should_fail_get_unsynced_commits) {
    async::PostTask(dispatcher_, [callback = std::move(callback)] {
      callback(storage::Status::IO_ERROR, {});
    });
    return;
  }
  std::vector<std::unique_ptr<const storage::Commit>> results;
  results.resize(unsynced_commits_to_return.size());
  std::transform(unsynced_commits_to_return.begin(),
                 unsynced_commits_to_return.end(), results.begin(),
                 [](const std::unique_ptr<const storage::Commit>& commit) {
                   return commit->Clone();
                 });
  async::PostTask(dispatcher_, [results = std::move(results),
                                callback = std::move(callback)]() mutable {
    callback(storage::Status::OK, std::move(results));
  });
}

void TestPageStorage::MarkCommitSynced(
    const storage::CommitId& commit_id,
    fit::function<void(storage::Status)> callback) {
  unsynced_commits_to_return.erase(
      std::remove_if(
          unsynced_commits_to_return.begin(), unsynced_commits_to_return.end(),
          [&commit_id](const std::unique_ptr<const storage::Commit>& commit) {
            return commit->GetId() == commit_id;
          }),
      unsynced_commits_to_return.end());
  commits_marked_as_synced.insert(commit_id);
  async::PostTask(dispatcher_, [callback = std::move(callback)] {
    callback(storage::Status::OK);
  });
}

void TestPageStorage::SetSyncMetadata(
    fxl::StringView key, fxl::StringView value,
    fit::function<void(storage::Status)> callback) {
  sync_metadata[key.ToString()] = value.ToString();
  async::PostTask(dispatcher_, [callback = std::move(callback)] {
    callback(storage::Status::OK);
  });
}

void TestPageStorage::GetSyncMetadata(
    fxl::StringView key,
    fit::function<void(storage::Status, std::string)> callback) {
  auto it = sync_metadata.find(key.ToString());
  if (it == sync_metadata.end()) {
    async::PostTask(dispatcher_, [callback = std::move(callback)] {
      callback(storage::Status::NOT_FOUND, "");
    });
    return;
  }
  async::PostTask(dispatcher_,
                  [callback = std::move(callback), metadata = it->second] {
                    callback(storage::Status::OK, metadata);
                  });
}

}  // namespace cloud_sync
