// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/storage/savegame.h"

#include <algorithm>

#include "base/file_util.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/optional.h"
#include "base/path_service.h"
#include "cobalt/storage/store_upgrade/upgrade.h"
#include "starboard/storage.h"
#include "starboard/user.h"

namespace cobalt {
namespace storage {
namespace {

using cobalt::storage::store_upgrade::IsUpgradeRequired;
using cobalt::storage::store_upgrade::UpgradeStore;

// An arbitrary max size for the save game file so that, for example, a corrupt
// filesystem cannot cause us to allocate a fatally large memory buffer.
size_t kMaxSaveGameSizeBytes = 4 * 1024 * 1024;

bool WriteRecord(const scoped_ptr<starboard::StorageRecord>& record,
                 const Savegame::ByteVector& bytes);

bool Upgrade(Savegame::ByteVector* bytes_ptr,
             const scoped_ptr<starboard::StorageRecord>& record) {
  DLOG(INFO) << "UPGRADING Record with size=" << bytes_ptr->size();
  if (IsUpgradeRequired(*bytes_ptr)) {
    if (!UpgradeStore(bytes_ptr)) {
      DLOG(ERROR) << "Upgrade failed";
      return false;
    }
  }

  WriteRecord(record, *bytes_ptr);
  DLOG(INFO) << "UPGRADING bytes_ptr.size=" << bytes_ptr->size();
  return true;
}

bool ReadRecord(Savegame::ByteVector* bytes_ptr, size_t max_to_read,
                const scoped_ptr<starboard::StorageRecord>& record) {
  if (!record->IsValid()) {
    DLOG(WARNING) << __FUNCTION__ << ": Invalid StorageRecord";
    return false;
  }

  int64_t size = record->GetSize();
  if (size < 0) {
    DLOG(WARNING) << "StorageRecord::GetSize failed";
    return false;
  }

  if (static_cast<size_t>(size) > max_to_read) {
    DLOG(WARNING) << "Savegame larger than max allowed size";
    return false;
  }

  Savegame::ByteVector& bytes = *bytes_ptr;
  bytes.resize(static_cast<size_t>(size));
  if (bytes.empty()) {
    return true;
  }

  int64_t bytes_read =
      record->Read(reinterpret_cast<char*>(bytes.data()), size);
  bytes.resize(
      static_cast<size_t>(std::max(static_cast<int64_t>(0), bytes_read)));

  bool success = (bytes_read == size);
  if (success) {
    DLOG(INFO) << "Successfully read storage record.";
  }
  if (!Upgrade(bytes_ptr, record)) {
    DLOG(WARNING) << __FUNCTION__ << ": Upgrade Failed";
    return false;
  }
  return success;
}

bool WriteRecord(const scoped_ptr<starboard::StorageRecord>& record,
                 const Savegame::ByteVector& bytes) {
  int64_t byte_count = static_cast<int64_t>(bytes.size());
  bool success =
      record->Write(reinterpret_cast<const char*>(bytes.data()), byte_count);
  if (success) {
    DLOG(INFO) << "Successfully wrote storage record.";
  }
  return success;
}

scoped_ptr<starboard::StorageRecord> CreateRecord(
    const base::optional<std::string>& id) {
#if SB_API_VERSION >= 6
  if (id) {
    return make_scoped_ptr(new starboard::StorageRecord(id->c_str()));
  }
#else  // SB_API_VERSION >= 6
  UNREFERENCED_PARAMETER(id);
#endif  // SB_API_VERSION >= 6
  return make_scoped_ptr(new starboard::StorageRecord());
}

bool EnsureRecord(scoped_ptr<starboard::StorageRecord>* record,
                  const base::optional<std::string>& id) {
  if (!(*record) || !(*record)->IsValid()) {
    // Might have been deleted, so we'll create a new one.
    (*record) = CreateRecord(id);
  }

  if (!(*record)->IsValid()) {
    DLOG(WARNING) << __FUNCTION__ << ": Invalid StorageRecord: Signed in?";
    return false;
  }

  return true;
}

// Savegame implementation that writes to the Starboard Storage API.
class SavegameStarboard : public Savegame {
 public:
  explicit SavegameStarboard(const Options& options);
  ~SavegameStarboard() override;
  bool PlatformRead(ByteVector* bytes, size_t max_to_read) override;
  bool PlatformWrite(const ByteVector& bytes) override;
  bool PlatformDelete() override;

 private:
  bool MigrateFromFallback();
  scoped_ptr<starboard::StorageRecord> record_;
};

SavegameStarboard::SavegameStarboard(const Options& options)
    : Savegame(options) {
  EnsureRecord(&record_, options_.id);
}

SavegameStarboard::~SavegameStarboard() {
  if (options_.delete_on_destruction) {
    Delete();
  }
}

bool SavegameStarboard::PlatformRead(ByteVector* bytes_ptr,
                                     size_t max_to_read) {
  bool success = ReadRecord(bytes_ptr, max_to_read, record_);
  if (success && !bytes_ptr->empty()) {
    return true;
  }

  if (!options_.fallback_to_default_id) {
    return false;
  }

  if (!MigrateFromFallback()) {
    DLOG(WARNING) << __FUNCTION__ << ": Migration Failed";
    return false;
  }

  // Now read the migrated data.
  return ReadRecord(bytes_ptr, max_to_read, record_);
}

bool SavegameStarboard::PlatformWrite(const ByteVector& bytes) {
  if (!EnsureRecord(&record_, options_.id)) {
    return false;
  }

  return WriteRecord(record_, bytes);
}

bool SavegameStarboard::PlatformDelete() {
  if (!record_->IsValid()) {
    DLOG(WARNING) << __FUNCTION__ << ": Invalid StorageRecord";
    return false;
  }

  return record_->Delete();
}

bool SavegameStarboard::MigrateFromFallback() {
  ByteVector buffer;
  if (!EnsureRecord(&record_, options_.id)) {
    DLOG(WARNING) << __FUNCTION__ << ": "
                  << "Failed to ensure record for ID: " << options_.id;
    return false;
  }

  scoped_ptr<starboard::StorageRecord> fallback_record;
  if (!EnsureRecord(&fallback_record, base::nullopt)) {
    DLOG(WARNING) << __FUNCTION__ << ": "
                  << "Failed to open default record.";
    return false;
  }

  if (!ReadRecord(&buffer, kMaxSaveGameSizeBytes, fallback_record)) {
    DLOG(WARNING) << __FUNCTION__ << ": "
                  << "Failed to read default record.";
    return false;
  }

  if (buffer.size() == 0) {
    // We migrated nothing successfully.
    DLOG(INFO) << "Migrated storage record data successfully (but trivially, "
               << "there was no data).";
    return true;
  }

  if (!WriteRecord(record_, buffer)) {
    DLOG(WARNING) << __FUNCTION__ << ": "
                  << "Failed to write record for ID: " << options_.id;
    return false;
  }

  // Flush the migrated record by closing and reopening it.
  record_.reset();
  if (!EnsureRecord(&record_, options_.id)) {
    return false;
  }

  // Now cleanup the fallback record.
  fallback_record->Delete();
  DLOG(INFO) << "Migrated storage record data successfully for user id: "
             << options_.id;
  return true;
}

}  // namespace

// static
scoped_ptr<Savegame> Savegame::Create(const Options& options) {
  return make_scoped_ptr(new SavegameStarboard(options)).PassAs<Savegame>();
}

}  // namespace storage
}  // namespace cobalt
