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

#include "peridot/bin/sessionmgr/storage/session_storage.h"

#include <lib/fidl/cpp/clone.h>
#include <lib/fxl/functional/make_copyable.h>
#include <lib/fxl/random/uuid.h>
#include <unordered_set>

#include "peridot/bin/sessionmgr/storage/constants_and_utils.h"
#include "peridot/bin/sessionmgr/storage/session_storage_xdr.h"
#include "peridot/lib/fidl/clone.h"
#include "peridot/lib/ledger_client/operations.h"

namespace modular {

SessionStorage::SessionStorage(LedgerClient* ledger_client,
                               LedgerPageId page_id)
    : PageClient("SessionStorage", ledger_client, page_id, kStoryKeyPrefix),
      ledger_client_(ledger_client) {
  FXL_DCHECK(ledger_client_ != nullptr);
}

namespace {

// TODO(rosswang): replace with |std::string::starts_with| after C++20
bool StartsWith(const std::string& string, const std::string& prefix) {
  return string.compare(0, prefix.size(), prefix) == 0;
}

fidl::StringPtr StoryNameToStoryDataKey(fidl::StringPtr story_name) {
  // Not escaped, because only one component after the prefix.
  return kStoryDataKeyPrefix + story_name.get();
}

fidl::StringPtr StoryNameFromStoryDataKey(fidl::StringPtr key) {
  return key->substr(sizeof(kStoryDataKeyPrefix) - 1);
}

fidl::StringPtr StoryNameToStorySnapshotKey(fidl::StringPtr story_name) {
  // Not escaped, because only one component after the prefix.
  return kStorySnapshotKeyPrefix + story_name.get();
}

OperationBase* MakeGetStoryDataCall(
    fuchsia::ledger::Page* const page, fidl::StringPtr story_name,
    std::function<void(fuchsia::modular::internal::StoryDataPtr)> result_call) {
  return new ReadDataCall<fuchsia::modular::internal::StoryData>(
      page, StoryNameToStoryDataKey(story_name), true /* not_found_is_ok */,
      XdrStoryData, std::move(result_call));
};

OperationBase* MakeWriteStoryDataCall(
    fuchsia::ledger::Page* const page,
    fuchsia::modular::internal::StoryDataPtr story_data,
    std::function<void()> result_call) {
  return new WriteDataCall<fuchsia::modular::internal::StoryData>(
      page, StoryNameToStoryDataKey(story_data->story_info.id), XdrStoryData,
      std::move(story_data), std::move(result_call));
};

class CreateStoryCall
    : public LedgerOperation<fidl::StringPtr, fuchsia::ledger::PageId> {
 public:
  CreateStoryCall(
      fuchsia::ledger::Ledger* const ledger,
      fuchsia::ledger::Page* const root_page, fidl::StringPtr story_name,
      fidl::VectorPtr<fuchsia::modular::StoryInfoExtraEntry> extra_info,
      fuchsia::modular::StoryOptions story_options, ResultCall result_call)
      : LedgerOperation("SessionStorage::CreateStoryCall", ledger, root_page,
                        std::move(result_call)),
        story_name_(std::move(story_name)),
        extra_info_(std::move(extra_info)),
        story_options_(std::move(story_options)) {}

 private:
  void Run() override {
    FlowToken flow{this, &story_name_, &story_page_id_};
    ledger()->GetPage(nullptr, story_page_.NewRequest(),
                      Protect([this, flow](fuchsia::ledger::Status status) {
                        if (status != fuchsia::ledger::Status::OK) {
                          FXL_LOG(ERROR) << trace_name() << " "
                                         << "Ledger.GetPage() "
                                         << fidl::ToUnderlying(status);
                        }
                      }));
    story_page_->GetId([this, flow](fuchsia::ledger::PageId id) {
      story_page_id_ = std::move(id);
      Cont(flow);
    });
  }

  void Cont(FlowToken flow) {
    // TODO(security), cf. FW-174. This ID is exposed in public services
    // such as fuchsia::modular::StoryProvider.PreviousStories(),
    // fuchsia::modular::StoryController.GetInfo(),
    // fuchsia::modular::ModuleContext.GetStoryName(). We need to ensure this
    // doesn't expose internal information by being a page ID.
    // TODO(thatguy): Generate a GUID instead.
    if (!story_name_ || story_name_->empty()) {
      story_name_ = fxl::GenerateUUID();
    }

    story_data_ = fuchsia::modular::internal::StoryData::New();
    story_data_->story_name = story_name_;
    story_data_->story_options = std::move(story_options_);
    story_data_->story_page_id = CloneOptional(story_page_id_);
    story_data_->story_info.id = story_name_;
    story_data_->story_info.last_focus_time = 0;
    story_data_->story_info.extra = std::move(extra_info_);

    operation_queue_.Add(MakeWriteStoryDataCall(page(), std::move(story_data_),
                                                [this, flow] {}));
  }

  fidl::StringPtr story_name_;
  fidl::VectorPtr<fuchsia::modular::StoryInfoExtraEntry> extra_info_;
  fuchsia::modular::StoryOptions story_options_;

  fuchsia::ledger::PagePtr story_page_;
  fuchsia::modular::internal::StoryDataPtr story_data_;

  fuchsia::ledger::PageId story_page_id_;

  // Sub operations run in this queue.
  OperationQueue operation_queue_;

  FXL_DISALLOW_COPY_AND_ASSIGN(CreateStoryCall);
};

}  // namespace

FuturePtr<fidl::StringPtr, fuchsia::ledger::PageId> SessionStorage::CreateStory(
    fidl::StringPtr story_name,
    fidl::VectorPtr<fuchsia::modular::StoryInfoExtraEntry> extra_info,
    fuchsia::modular::StoryOptions story_options) {
  auto ret = Future<fidl::StringPtr, fuchsia::ledger::PageId>::Create(
      "SessionStorage.CreateStory.ret");
  operation_queue_.Add(new CreateStoryCall(
      ledger_client_->ledger(), page(), std::move(story_name),
      std::move(extra_info), std::move(story_options), ret->Completer()));
  return ret;
}

FuturePtr<fidl::StringPtr, fuchsia::ledger::PageId> SessionStorage::CreateStory(
    fidl::VectorPtr<fuchsia::modular::StoryInfoExtraEntry> extra_info,
    fuchsia::modular::StoryOptions story_options) {
  return CreateStory(nullptr /* story_name */, std::move(extra_info),
                     std::move(story_options));
}

namespace {
class DeleteStoryCall : public Operation<> {
 public:
  DeleteStoryCall(fuchsia::ledger::Ledger* const ledger,
                  fuchsia::ledger::Page* const session_page,
                  fidl::StringPtr story_name, ResultCall result_call)
      : Operation("SessionStorage::DeleteStoryCall", std::move(result_call)),
        ledger_(ledger),
        session_page_(session_page),
        story_name_(story_name) {}

 private:
  void Run() override {
    FlowToken flow{this};
    operation_queue_.Add(MakeGetStoryDataCall(
        session_page_, story_name_, [this, flow](auto story_data) {
          if (!story_data)
            return;
          story_data_ = std::move(*story_data);
          Cont1(flow);
        }));
  }

  void Cont1(FlowToken flow) {
    // Get the story page so we can remove its contents.
    ledger_->GetPage(
        std::move(story_data_.story_page_id), story_page_.NewRequest(),
        [this, flow, story_name = story_data_.story_info.id](
            fuchsia::ledger::Status status) {
          if (status != fuchsia::ledger::Status::OK) {
            FXL_LOG(ERROR) << "Ledger.GetPage() for story " << story_name
                           << ": " << fidl::ToUnderlying(status);
            return;
          }
          Cont2(flow);
        });
  }

  void Cont2(FlowToken flow) {
    story_page_->Clear([this, flow, story_name = story_data_.story_info.id](
                           fuchsia::ledger::Status status) {
      if (status != fuchsia::ledger::Status::OK) {
        FXL_LOG(ERROR) << "Page.Clear() for story " << story_name << ": "
                       << fidl::ToUnderlying(status);
        return;
      }
      Cont3(flow);
    });
  }

  void Cont3(FlowToken flow) {
    // Remove the story data in the session page.
    session_page_->Delete(
        to_array(StoryNameToStoryDataKey(story_data_.story_info.id)),
        [this, flow](fuchsia::ledger::Status status) {
          // Deleting a key that doesn't exist is OK, not
          // KEY_NOT_FOUND.
          if (status != fuchsia::ledger::Status::OK) {
            FXL_LOG(ERROR) << "SessionStorage: Page.Delete() "
                           << fidl::ToUnderlying(status);
          }
          Cont4(flow);
        });
  }

  void Cont4(FlowToken flow) {
    // Remove the story snapshot in the session page.
    session_page_->Delete(
        to_array(StoryNameToStorySnapshotKey(story_data_.story_info.id)),
        [this, flow](fuchsia::ledger::Status status) {
          // Deleting a key that doesn't exist is OK, not
          // KEY_NOT_FOUND.
          if (status != fuchsia::ledger::Status::OK) {
            FXL_LOG(ERROR) << "SessionStorage: Page.Delete() "
                           << fidl::ToUnderlying(status);
          }
        });
  }

  fuchsia::ledger::Ledger* const ledger_;      // not owned
  fuchsia::ledger::Page* const session_page_;  // not owned
  const fidl::StringPtr story_name_;

  // Intermediate state.
  OperationQueue operation_queue_;
  fuchsia::modular::internal::StoryData story_data_;
  fuchsia::ledger::PagePtr story_page_;

  FXL_DISALLOW_COPY_AND_ASSIGN(DeleteStoryCall);
};
}  // namespace

FuturePtr<> SessionStorage::DeleteStory(fidl::StringPtr story_name) {
  auto ret = Future<>::Create("SessionStorage.DeleteStory.ret");
  operation_queue_.Add(new DeleteStoryCall(ledger_client_->ledger(), page(),
                                           story_name, ret->Completer()));
  return ret;
}

namespace {
class MutateStoryDataCall : public Operation<> {
 public:
  MutateStoryDataCall(
      fuchsia::ledger::Page* const page, fidl::StringPtr story_name,
      std::function<bool(fuchsia::modular::internal::StoryData* story_data)>
          mutate,
      ResultCall result_call)
      : Operation("SessionStorage::MutateStoryDataCall",
                  std::move(result_call)),
        page_(page),
        story_name_(story_name),
        mutate_(std::move(mutate)) {}

 private:
  void Run() override {
    FlowToken flow{this};

    operation_queue_.Add(MakeGetStoryDataCall(
        page_, story_name_,
        [this, flow](fuchsia::modular::internal::StoryDataPtr story_data) {
          if (!story_data) {
            // If the story doesn't exist, it was deleted.
            return;
          }
          if (!mutate_(story_data.get())) {
            // If no mutation happened, we're done.
            return;
          }

          operation_queue_.Add(
              MakeWriteStoryDataCall(page_, std::move(story_data), [flow] {}));
        }));
  }

  fuchsia::ledger::Page* const page_;  // not owned
  const fidl::StringPtr story_name_;
  std::function<bool(fuchsia::modular::internal::StoryData* story_data)>
      mutate_;

  OperationQueue operation_queue_;

  FXL_DISALLOW_COPY_AND_ASSIGN(MutateStoryDataCall);
};

}  // namespace

FuturePtr<> SessionStorage::UpdateLastFocusedTimestamp(
    fidl::StringPtr story_name, const int64_t ts) {
  auto mutate = [ts](fuchsia::modular::internal::StoryData* const story_data) {
    if (story_data->story_info.last_focus_time == ts) {
      return false;
    }
    story_data->story_info.last_focus_time = ts;
    return true;
  };

  auto ret = Future<>::Create("SessionStorage.UpdateLastFocusedTimestamp.ret");
  operation_queue_.Add(
      new MutateStoryDataCall(page(), story_name, mutate, ret->Completer()));
  return ret;
}

FuturePtr<fuchsia::modular::internal::StoryDataPtr>
SessionStorage::GetStoryData(fidl::StringPtr story_name) {
  auto ret = Future<fuchsia::modular::internal::StoryDataPtr>::Create(
      "SessionStorage.GetStoryData.ret");
  operation_queue_.Add(
      MakeGetStoryDataCall(page(), story_name, ret->Completer()));
  return ret;
}

// Returns a Future vector of StoryData for all stories in this session.
FuturePtr<std::vector<fuchsia::modular::internal::StoryData>>
SessionStorage::GetAllStoryData() {
  auto ret =
      Future<std::vector<fuchsia::modular::internal::StoryData>>::Create(
          "SessionStorage.GetAllStoryData.ret");
  operation_queue_.Add(
      new ReadAllDataCall<fuchsia::modular::internal::StoryData>(
          page(), kStoryDataKeyPrefix, XdrStoryData, ret->Completer()));
  return ret;
}

FuturePtr<> SessionStorage::UpdateStoryOptions(
    fidl::StringPtr story_name, fuchsia::modular::StoryOptions story_options) {
  auto ret = Future<>::Create("SessionStorage.SetOptions.ret");
  auto mutate = fxl::MakeCopyable(
      [story_options = std::move(story_options)](
          fuchsia::modular::internal::StoryData* story_data) mutable {
        if (story_data->story_options != story_options) {
          story_data->story_options = std::move(story_options);
          return true;
        }
        return false;
      });
  operation_queue_.Add(new MutateStoryDataCall(
      page(), story_name, std::move(mutate), ret->Completer()));
  return ret;
}

FuturePtr<std::unique_ptr<StoryStorage>> SessionStorage::GetStoryStorage(
    fidl::StringPtr story_name) {
  auto returned_future = Future<std::unique_ptr<StoryStorage>>::Create(
      "SessionStorage.GetStoryStorage.returned_future");

  operation_queue_.Add(MakeGetStoryDataCall(
      page(), story_name,
      [this, returned_future,
       story_name](fuchsia::modular::internal::StoryDataPtr story_data) {
        if (story_data) {
          auto story_storage = std::make_unique<StoryStorage>(
              ledger_client_, *story_data->story_page_id);
          returned_future->Complete(std::move(story_storage));
        } else {
          returned_future->Complete(nullptr);
        }
      }));

  return returned_future;
}

namespace {

class WriteSnapshotCall : public Operation<> {
 public:
  WriteSnapshotCall(PageClient* page_client, fidl::StringPtr story_name,
                    fuchsia::mem::Buffer snapshot, ResultCall result_call)
      : Operation("SessionStorage::WriteSnapshotCall", std::move(result_call)),
        page_client_(page_client),
        key_(StoryNameToStorySnapshotKey(story_name)),
        snapshot_(std::move(snapshot)) {}

 private:
  void Run() override {
    FlowToken flow{this};
    page_client_->page()->CreateReferenceFromBuffer(
        std::move(snapshot_),
        [this, flow](fuchsia::ledger::Status status,
                     std::unique_ptr<fuchsia::ledger::Reference> reference) {
          if (status != fuchsia::ledger::Status::OK) {
            FXL_LOG(ERROR) << trace_name()
                           << " PageSnapshot.CreateReferenceFromBuffer() "
                           << fidl::ToUnderlying(status);
            return;
          } else if (!reference) {
            return;
          }

          PutReference(std::move(reference), flow);
        });
  }

  void PutReference(std::unique_ptr<fuchsia::ledger::Reference> reference,
                    FlowToken flow) {
    page_client_->page()->PutReference(
        to_array(key_), std::move(*reference),
        // TODO(MI4-1425): Experiment with declaring lazy priority.
        fuchsia::ledger::Priority::EAGER,
        [this, flow](fuchsia::ledger::Status status) {
          if (status != fuchsia::ledger::Status::OK) {
            FXL_LOG(ERROR) << trace_name() << " PageSnapshot.PutReference() "
                           << fidl::ToUnderlying(status);
          }
        });
  }

  PageClient* const page_client_;
  fidl::StringPtr key_;
  fuchsia::mem::Buffer snapshot_;

  FXL_DISALLOW_COPY_AND_ASSIGN(WriteSnapshotCall);
};

class ReadSnapshotCall : public Operation<fuchsia::mem::BufferPtr> {
 public:
  ReadSnapshotCall(PageClient* page_client, fidl::StringPtr story_name,
                   ResultCall result_call)
      : Operation("SessionStorage::ReadSnapshotCall", std::move(result_call)),
        page_client_(page_client),
        key_(StoryNameToStorySnapshotKey(story_name)) {}

 private:
  void Run() override {
    FlowToken flow{this, &snapshot_};

    page_snapshot_ = page_client_->NewSnapshot(
        /* on_error = */ [this] { Done(nullptr); });
    page_snapshot_->Get(
        to_array(key_), [this, flow](fuchsia::ledger::Status status,
                                     fuchsia::mem::BufferPtr snapshot) {
          // TODO(MI4-1425): Handle NEEDS_FETCH status if using lazy priority.
          switch (status) {
            case fuchsia::ledger::Status::KEY_NOT_FOUND:
              return;
            case fuchsia::ledger::Status::OK:
              snapshot_ = std::move(snapshot);
              return;
            default:
              FXL_LOG(ERROR) << trace_name() << " PageSnapshot.Get() "
                             << fidl::ToUnderlying(status);
              return;
          }
        });
  }

  // Input parameters.
  PageClient* const page_client_;
  fidl::StringPtr key_;

  // Intermediate state.
  fuchsia::ledger::PageSnapshotPtr page_snapshot_;

  // Return values.
  fuchsia::mem::BufferPtr snapshot_;

  FXL_DISALLOW_COPY_AND_ASSIGN(ReadSnapshotCall);
};
}  // namespace

FuturePtr<> SessionStorage::WriteSnapshot(fidl::StringPtr story_name,
                                          fuchsia::mem::Buffer snapshot) {
  auto ret = Future<>::Create("SessionStorage.WriteSnapshot.ret");
  operation_queue_.Add(new WriteSnapshotCall(
      this, story_name, std::move(snapshot), ret->Completer()));
  return ret;
}

FuturePtr<fuchsia::mem::BufferPtr> SessionStorage::ReadSnapshot(
    fidl::StringPtr story_name) {
  auto ret = Future<fuchsia::mem::BufferPtr>::Create(
      "SessionStorage.ReadSnapshot.ret");
  operation_queue_.Add(
      new ReadSnapshotCall(this, story_name, ret->Completer()));
  return ret;
}

void SessionStorage::OnPageChange(const std::string& key,
                                  const std::string& value) {
  if (StartsWith(key, kStoryDataKeyPrefix)) {
    auto story_data = fuchsia::modular::internal::StoryData::New();
    if (!XdrRead(value, &story_data, XdrStoryData)) {
      FXL_LOG(ERROR)
          << "SessionStorage::OnPageChange : could not decode ledger "
             "value for key "
          << key << "\nvalue:\n"
          << value;
      return;
    }

    auto story_name = StoryNameFromStoryDataKey(key);
    if (on_story_updated_) {
      on_story_updated_(std::move(story_name), std::move(*story_data));
    }
  } else {
    // No-op.
  }
}

void SessionStorage::OnPageDelete(const std::string& key) {
  if (on_story_deleted_) {
    // Call to StoryNameFromStoryDataKey() needed because a deleted story is
    // modelled by deleting the key, and then the value is not available.
    // TODO(thatguy,mesch): Change PageClient to supply values of deleted keys
    // and/or change modeling of deleted stories.
    on_story_deleted_(StoryNameFromStoryDataKey(key));
  }
}

}  // namespace modular
